«1. Обзор
Профилировщики выборки Java обычно разрабатываются с использованием интерфейса инструментов JVM (JVMTI) и собирают трассировки стека в безопасной точке. Следовательно, эти профилировщики выборки могут страдать от проблемы смещения точки безопасности.
Для целостного представления о приложении нам нужен профилировщик выборки, который не требует, чтобы потоки находились в безопасных точках, и может собирать трассировки стека в любое время, чтобы избежать проблемы смещения безопасных точек.
В этом руководстве мы рассмотрим async-profiler вместе с различными методами профилирования, которые он предлагает.
2. async-profiler
async-profiler — это профилировщик выборки для любого JDK на основе HotSpot JVM. Он имеет низкие накладные расходы и не зависит от JVMTI.
Это позволяет избежать проблемы смещения точек безопасности, используя API AsyncGetCallTrace, предоставляемый HotSpot JVM, для профилирования путей кода Java, и perf_events Linux для профилирования путей собственного кода.
Другими словами, профилировщик сопоставляет стеки вызовов как 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
$ ./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
Всегда полезно заранее проверить все параметры, доступные с помощью async-profiler:
~~ ~ Многие из показанных опций пригодятся в последующих разделах.
3.2. Конфигурация ядра
При использовании async-profiler на платформе Linux мы должны убедиться, что наше ядро настроено на сбор стеков вызовов с использованием perf_events всеми пользователями:
$ sudo sh -c 'echo 1 >/proc/sys/kernel/perf_event_paranoid'
Сначала мы установим perf_event_paranoid в 1, что разрешить профилировщику собирать информацию о производительности:
$ sudo sh -c 'echo 0 >/proc/sys/kernel/kptr_restrict'
Затем мы установим kptr_restrict в 0, чтобы снять ограничения на раскрытие адресов ядра:
Однако асинхронный профилировщик будет работать сам по себе на платформа macOS.
$ java -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -jar path-to-jar-file
Теперь, когда наша платформа готова, мы можем создать наше приложение для профилирования и запустить его с помощью команды Java:
Здесь мы запустили наше приложение для профилирования, используя -XX:+UnlockDiagnosticVMOptions -XX:+ Флаги DebugNonSafepoints JVM, которые настоятельно рекомендуются для получения точных результатов.
Теперь, когда мы готовы профилировать наше приложение, давайте рассмотрим различные типы профилирования, поддерживаемые асинхронным профилировщиком.
4. Профилирование ЦП
Async-profiler собирает образцы трассировки стека методов Java, включая код JVM, собственный класс и функции ядра, при профилировании ЦП.
$ ./profiler.sh -e cpu -d 30 -o summary 66959
Started [cpu] profiling
--- Execution profile ---
Total samples : 28
Frame buffer usage : 0.069%
Давайте профилируем наше приложение, используя его PID:
Здесь мы определили событие профилирования процессора с помощью параметра -e. Затем мы использовали параметр -d \u003cduration\u003e для сбора выборки в течение 30 секунд.
Наконец, опция -o полезна для определения выходного формата, такого как сводка, HTML, трассировка, SVG и дерево.
$ ./profiler.sh -e cpu -d 30 -f cpu_profile.html 66959
Давайте создадим HTML-вывод, пока ЦП профилирует наше приложение:
Здесь мы видим, что HTML-вывод позволяет нам расширять, сворачивать и искать образцы.
Кроме того, async-profiler поддерживает графы пламени из коробки.
$ ./profiler.sh -e cpu -d 30 -f cpu_profile.svg 66959
Давайте сгенерируем диаграмму пламени, используя файл с расширением .svg для профиля ЦП нашего приложения:
Здесь полученная диаграмма пламени показывает пути кода Java зеленым цветом, C++ желтым цветом и пути системного кода. в красном.
5. Профилирование распределения
Точно так же мы можем собирать образцы распределения памяти, не используя навязчивую технику, такую как инструментирование байт-кода.
async-profiler использует метод выборки на основе TLAB (Thread Local Allocation Buffer) для сбора выборок выделения кучи выше среднего размера TLAB.
$ ./profiler.sh -e alloc -d 30 -f alloc_profile.svg 66255
Используя событие alloc, мы можем позволить профилировщику собирать выделение кучи нашего профилирующего приложения:
Здесь мы видим, что клонирование объекта выделило большую часть памяти, которую иначе было бы трудно выделить. воспринимать, глядя на код.
6. Профилирование настенных часов
«Кроме того, async-profiler может выполнять выборку всех потоков независимо от их статуса — например, запущенного, спящего или заблокированного — с помощью профиля настенных часов.
Это может оказаться полезным при устранении неполадок во время запуска приложения.
$ ./profiler.sh -e wall -t -d 30 -f wall_clock_profile.svg 66959
Определив событие стены, мы можем настроить профилировщик для сбора образцов всех потоков:
Здесь мы использовали профилировщик настенных часов в режиме для каждого потока с использованием параметра -t, что настоятельно рекомендуется при профилировании всех потоков.
$ ./profiler.sh list 66959
Basic events:
cpu
alloc
lock
wall
itimer
Java method calls:
ClassName.methodName
Кроме того, мы можем проверить все события профилирования, поддерживаемые нашей JVM, используя параметр списка:
7. async-profiler With IntelliJ IDEA
IntelliJ IDEA включает интеграцию с async-profiler инструмент профилирования для Java.
7.1. Конфигурации профилировщика
Мы можем настроить асинхронный профилировщик в IntelliJ IDEA, выбрав пункт меню Java Profiler в меню «Настройки/Предпочтения» \u003e «Сборка, выполнение, развертывание»:
Кроме того, для быстрого использования мы можем выбрать любую предопределенную конфигурацию, например CPU Profiler и Allocation Profiler, которые предлагает IntelliJ IDEA.
Точно так же мы можем скопировать шаблон профилировщика и отредактировать параметры агента для конкретных случаев использования.
7.2. Профилирование приложения с использованием IntelliJ IDEA
Есть несколько способов проанализировать наше приложение с помощью профилировщика.
Например, мы можем выбрать приложение и выбрать Запустить \u003cимя приложения\u003e с опцией \u003cимя конфигурации профилировщика\u003e:
Или мы можем щелкнуть на панели инструментов и выбрать Запустить \u003cимя приложения\u003e с \u003cимя конфигурации профилировщика\u003e: \u003e вариант:
Или, выбрав параметр «Выполнить с профилировщиком» в меню «Выполнить», затем выбрав \u003cимя конфигурации профилировщика\u003e:
Кроме того, мы можем увидеть параметр «Присоединить профилировщик к процессу» в меню «Выполнить». Откроется диалоговое окно, позволяющее выбрать процесс для присоединения:
После того, как наше приложение будет профилировано, мы можем проанализировать результат профилирования с помощью панели инструментов Profiler в нижней части IDE.
Результат профилирования нашего приложения будет выглядеть так:
Он показывает результаты по потокам в различных выходных форматах, таких как графики пламени, деревья вызовов и список методов.
Кроме того, мы можем выбрать опцию Profiler в меню View \u003e Tool Windows, чтобы увидеть результаты:
8. Заключение
В этой статье мы рассмотрели async-profiler вместе с несколькими методами профилирования.
Во-первых, мы увидели, как настроить ядро при использовании платформы Linux, и несколько рекомендуемых флагов JVM для начала профилирования нашего приложения для получения точных результатов.