Ръководство за async-профилиране

1. Общ преглед

Java Sampling Profilers обикновено се проектират с помощта на JVM Tool Interface (JVMTI) и събират следи от стека в безопасна точка. Следователно тези профили за вземане на проби могат да страдат от проблема с пристрастия на безопасна точка.

За цялостен изглед на приложението се нуждаем от профилиращ извадка, който не изисква нишките да са в безопасни точки и може да събира следите на стека по всяко време, за да избегне проблема с пристрастията на защитната точка .

В този урок ще разгледаме async-profiler заедно с различни техники за профилиране, които той предлага.

2. async-профилиращ

async-profiler е профилиращ диск за всеки JDK, базиран на HotSpot JVM. Той има ниски режийни разходи и не разчита на JVMTI.

Той избягва проблема с пристрастието на безопасна точка, като използва API на AsyncGetCallTrace, предоставен от HotSpot JVM, за да профилира Java кодовите пътища и Linux_per_events за профилиране на родните кодови пътища.

С други думи, профилиращият съвпада с стекове от обаждания както на Java код, така и на пътеки на местния код, за да даде точни резултати.

3. Настройка

3.1. Инсталация

Първо ще изтеглим най-новата версия на async-profiler, базирана на нашата платформа. В момента той поддържа само Linux и macOS платформи.

Веднъж изтеглени, можем да проверим дали работи на нашата платформа:

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

Винаги е добра идея да проверите предварително всички опции, налични с async-profiler :

$ ./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

Много от показаните опции ще ви бъдат полезни в следващите раздели.

3.2. Конфигурация на ядрото

Когато използваме async-profiler на платформата Linux, трябва да се уверим, че сме конфигурирали нашето ядро ​​за улавяне на стекове повиквания, използвайки perf_events от всички потребители:

Първо ще зададем perf_event_paranoid на 1, което ще позволи на профилиращия да събира информация за ефективността:

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

След това ще зададем kptr_restrict на 0, за да премахнем ограниченията за излагане на адресите на ядрото:

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

Въпреки това, асинхронният профилист ще работи сам по себе си на платформата macOS.

Сега, когато нашата платформа е готова, можем да изградим нашето приложение за профилиране и да го стартираме с помощта на командата Java:

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

Тук стартирахме нашето приложение за профилиране, използвайки -XX: + UnlockDiagnosticVMOptions -XX: + DebugNonSafepoints JVM флагове, които са силно препоръчителни за точни резултати .

Сега, когато сме готови да профилираме нашето приложение, нека разгледаме различни видове профилиране, поддържани от async-profiler .

4. Профилиране на процесора

Async-profiler събира примерни следи от стека на Java методи, включително JVM код, собствен клас и функции на ядрото, при профилиране на CPU.

Нека профилираме нашето приложение, използвайки неговия PID:

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

Тук дефинирахме събитието за профилиране на процесора с помощта на опцията -e . След това използвахме -d опция за събиране на пробата за 30 секунди.

И накрая, опцията -o е полезна за дефиниране на изходния формат като резюме, HTML, траси, SVG и дърво .

Нека създадем HTML изхода, докато CPU профилира нашето приложение:

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

Тук можем да видим, че HTML изходът ни позволява да разширяваме, свиваме и търсим пробите.

Освен това, асинхронният профилист поддържа графики на пламъка извън кутията .

Нека генерираме графика на пламъка, като използваме разширението на файла .svg за CPU профила на нашето приложение:

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

Тук получената графика на пламъка показва пътеките на Java кода в зелено, C ++ в жълто и системните пътеки в червено.

5. Профилиране на разпределение

По същия начин можем да събираме проби от разпределението на паметта, без да използваме натрапчива техника като байтовия инструментариум.

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.

Като алтернатива можем да изберем опцията Profiler под менюто View> Tool Windows, за да видим резултатите:

8. Заключение

В тази статия разгледахме асинхронния профилист , заедно с няколко техники за профилиране.

Първо, видяхме как да конфигурираме ядрото, когато използваме платформата Linux, и няколко препоръчителни флага на JVM, с които да започнем да профилираме приложението си, за да получим точни резултати.

След това разгледахме различни видове техники за профилиране като CPU, разпределение и стенен часовник.

И накрая, профилирахме приложение с async-профилиране, използвайки IntelliJ IDEA.