Una guida al profiler asincrono

1. Panoramica

I Java Sampling Profiler sono generalmente progettati utilizzando JVM Tool Interface (JVMTI) e raccolgono le tracce dello stack in un punto sicuro. Pertanto, questi profiler di campionamento possono soffrire del problema di bias del punto di sicurezza.

Per una visione olistica dell'applicazione, abbiamo bisogno di un profiler di campionamento che non richieda che i thread siano nei safepoint e che possa raccogliere le tracce dello stack in qualsiasi momento per evitare il problema del bias del safepoint .

In questo tutorial, esploreremo il profiler asincrono insieme alle varie tecniche di profiling che offre.

2. async-profiler

async-profiler è un profiler di campionamento per qualsiasi JDK basato sulla JVM HotSpot. Ha un overhead basso e non si basa su JVMTI.

Evita il problema del bias di safepoint utilizzando l' API AsyncGetCallTrace fornita da HotSpot JVM per profilare i percorsi del codice Java e perf_events di Linux per profilare i percorsi del codice nativo.

In altre parole, il profiler corrisponde agli stack di chiamate del codice Java e dei percorsi del codice nativo per produrre risultati accurati.

3. Configurazione

3.1. Installazione

Innanzitutto, scaricheremo l'ultima versione del profiler asincrono basato sulla nostra piattaforma. Attualmente supporta solo le piattaforme Linux e macOS.

Una volta scaricato, possiamo verificare se funziona sulla nostra piattaforma:

$ ./profiler.sh --version
Async-profiler 1.7.1 built on May 14 2020 Copyright 2016-2020 Andrei Pangin

È sempre una buona idea controllare in anticipo tutte le opzioni disponibili con il profiler asincrono :

$ ./profiler.sh
Usage: ./profiler.sh [action] [options] Actions: start start profiling and return immediately resume resume profiling without resetting collected data stop stop profiling check check if the specified profiling event is available status print profiling status list list profiling events supported by the target JVM collect collect profile for the specified period of time and then stop (default action) Options: -e event profiling event: cpu|alloc|lock|cache-misses etc. -d duration run profiling for seconds -f filename dump output to -i interval sampling interval in nanoseconds -j jstackdepth maximum Java stack depth -b bufsize frame buffer size -t profile different threads separately -s simple class names instead of FQN -g print method signatures -a annotate Java method names -o fmt output format: summary|traces|flat|collapsed|svg|tree|jfr -I include output only stack traces containing the specified pattern -X exclude exclude stack traces with the specified pattern -v, --version display version string --title string SVG title --width px SVG width --height px SVG frame height --minwidth px skip frames smaller than px --reverse generate stack-reversed FlameGraph / Call tree --all-kernel only include kernel-mode events --all-user only include user-mode events --cstack mode how to traverse C stack: fp|lbr|no is a numeric process ID of the target JVM or 'jps' keyword to find running JVM automatically

Molte delle opzioni mostrate torneranno utili nelle sezioni successive.

3.2. Configurazione del kernel

Quando si utilizza il profiler asincrono sulla piattaforma Linux, dobbiamo assicurarci di configurare il nostro kernel per acquisire stack di chiamate utilizzando perf_events da tutti gli utenti:

Innanzitutto, imposteremo perf_event_paranoid su 1, che consentirà al profiler di raccogliere informazioni sulle prestazioni:

$ sudo sh -c 'echo 1 >/proc/sys/kernel/perf_event_paranoid'

Quindi, imposteremo kptr_restrict su 0 per rimuovere le restrizioni sull'esposizione degli indirizzi del kernel:

$ sudo sh -c 'echo 0 >/proc/sys/kernel/kptr_restrict'

Tuttavia, il profiler asincrono funzionerà da solo sulla piattaforma macOS.

Ora che la nostra piattaforma è pronta, possiamo creare la nostra applicazione di profilazione ed eseguirla utilizzando il comando Java:

$ java -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -jar path-to-jar-file

Qui, abbiamo avviato la nostra app di profilazione utilizzando i flag JVM -XX: + UnlockDiagnosticVMOptions -XX: + DebugNonSafepoints altamente consigliati per risultati accurati .

Ora che siamo pronti per profilare la nostra applicazione, esploriamo i vari tipi di profilazione supportati dal profiler asincrono .

4. Profilazione CPU

Async-profiler raccoglie tracce dello stack di esempio dei metodi Java, incluso il codice JVM, la classe nativa e le funzioni del kernel, durante la profilazione della CPU.

Profiliamo la nostra applicazione utilizzando il suo PID:

$ ./profiler.sh -e cpu -d 30 -o summary 66959 Started [cpu] profiling --- Execution profile --- Total samples : 28 Frame buffer usage : 0.069%

Qui, abbiamo definito l' evento di profilazione della cpu utilizzando l' opzione -e . Quindi, abbiamo usato -d opzione per raccogliere il campione per 30 secondi.

Infine, l' opzione -o è utile per definire il formato di output come riepilogo, HTML, tracce, SVG e albero .

Creiamo l'output HTML mentre la CPU profila la nostra applicazione:

$ ./profiler.sh -e cpu -d 30 -f cpu_profile.html 66959

Qui possiamo vedere l'output HTML che ci consente di espandere, comprimere e cercare gli esempi.

Inoltre, il profiler asincrono supporta i grafici a fiamma predefiniti .

Generiamo un grafico a fiamma utilizzando l' estensione del file .svg per il profilo della CPU della nostra applicazione:

$ ./profiler.sh -e cpu -d 30 -f cpu_profile.svg 66959

Qui, il grafico a fiamma risultante mostra i percorsi del codice Java in verde, C ++ in giallo e i percorsi del codice di sistema in rosso.

5. Profilazione di allocazione

Allo stesso modo, possiamo raccogliere campioni di allocazione della memoria senza utilizzare una tecnica intrusiva come la strumentazione bytecode.

async-profiler uses the TLAB (Thread Local Allocation Buffer) based sampling technique to collect the samples of the heap allocation above the average size of TLAB.

By using the alloc event, we can enable the profiler to collect heap allocations of our profiling application:

$ ./profiler.sh -e alloc -d 30 -f alloc_profile.svg 66255

Here, we can see the object cloning has allocated a large part of memory, which is otherwise hard to perceive when looking at the code.

6. Wall-Clock Profiling

Also, async-profiler can sample all threads irrespective of their status – like running, sleeping, or blocked – by using the wall-clock profile.

This can prove handy when troubleshooting issues in the application start-up time.

By defining the wall event, we can configure the profiler to collect samples of all threads:

$ ./profiler.sh -e wall -t -d 30 -f wall_clock_profile.svg 66959

Here, we've used the wall-clock profiler in per-thread mode by using the -t option, which is highly recommended when profiling all threads.

Additionally, we can check all profiling events supported by our JVM by using the list option:

$ ./profiler.sh list 66959
Basic events: cpu alloc lock wall itimer Java method calls: ClassName.methodName

7. async-profiler With IntelliJ IDEA

IntelliJ IDEA features integration with async-profiler as a profiling tool for Java.

7.1. Profiler Configurations

We can configure async-profiler in IntelliJ IDEA by selecting the Java Profiler menu option at Settings/Preferences > Build, Execution, Deployment:

Also, for quick usage, we can choose any predefined configuration, like the CPU Profiler and the Allocation Profiler that IntelliJ IDEA offers.

Similarly, we can copy a profiler template and edit the Agent options for specific use cases.

7.2. Profile Application Using IntelliJ IDEA

There are a few ways to analyze our application with a profiler.

For instance, we can select the application and choose Run with option:

Or, we can click on the toolbar and choose the Run with option:

Or, by choosing the Run with Profiler option under the Run menu, then selecting the <profiler configuration name>:

Additionally, we can see the option to Attach Profiler to Process under the Run menu. It opens a dialog that lets us choose the process to attach:

Once our application is profiled, we can analyze the profiling result using the Profiler tool window bar at the bottom of the IDE.

The profiling result of our application will look like:

It shows the thread wise results in different output formats like flame graphs, call trees, and method list.

In alternativa, possiamo scegliere l' opzione Profiler nel menu Visualizza> Finestre degli strumenti per vedere i risultati:

8. Conclusione

In questo articolo, abbiamo esplorato il profiler asincrono , insieme ad alcune tecniche di profiling.

Innanzitutto, abbiamo visto come configurare il kernel quando si utilizza la piattaforma Linux e alcuni flag JVM consigliati per iniziare a profilare la nostra applicazione per ottenere risultati accurati.

Quindi, abbiamo esaminato vari tipi di tecniche di profilazione come CPU, allocazione e orologio da parete.

Infine, abbiamo profilato un'applicazione con un profiler asincrono utilizzando IntelliJ IDEA.