Рубрики
Без рубрики

Руководство по асинхронному профилировщику

Изучите async-profiler вместе с различными методами профилирования, которые он предлагает

Автор оригинала: 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.