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