Uber JVM Profiler предоставляет агент Java для распределенного сбора различных показателей и трассировок стека для процессов Hadoop/Spark JVM, например показателей ЦП/памяти/IO.
Uber JVM Profiler также предоставляет расширенные возможности профилирования для отслеживания произвольных методов и аргументов Java в пользовательском коде без необходимости изменения пользовательского кода. Эту функцию можно использовать для отслеживания задержки вызова узла имени HDFS для каждого приложения Spark и выявления узкого места узла имени. Он также может отслеживать пути к файлам HDFS, которые читает или записывает каждое приложение Spark, и идентифицировать «горячие» файлы для дальнейшей оптимизации.
Этот профилировщик изначально создан для профилирования приложений Spark, которые обычно имеют десятки или сотни процессов/машин для одного приложения, чтобы люди могли легко сопоставлять показатели этих разных процессов/машин. Это также универсальный агент Java, который можно использовать для любого процесса JVM.
mvn clean package
Эта команда создает файл jvm-profiler.jar со встроенными в него генераторами отчетов по умолчанию, такими как ConsoleOutputReporter, FileOutputReporter и KafkaOutputReporter. Если вы хотите объединить пользовательские репортеры, такие как RedisOutputReporter или InfluxDBOutputReporter, в файл jar, укажите идентификатор профиля maven для этого репортера в команде сборки. Например, чтобы создать файл jar с помощью RedisOutputReporter, вы можете выполнить команду mvn -P redis clean package
. Пожалуйста, проверьте файл pom.xml на наличие доступных пользовательских репортеров и идентификаторов их профилей.
Вы можете загрузить jar-файл jvm-profiler в HDFS, чтобы исполнители приложений Spark могли получить к нему доступ. Затем добавьте следующую конфигурацию при запуске приложения Spark:
--conf spark.jars=hdfs://hdfs_url/lib/jvm-profiler-1.0.0.jar
--conf spark.executor.extraJavaOptions=-javaagent:jvm-profiler-1.0.0.jar
Следующая команда запустит пример приложения с подключенным агентом профилировщика, который будет сообщать метрики на вывод консоли:
java -javaagent:target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.ConsoleOutputReporter,tag=mytag,metricInterval=5000,durationProfiling=com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod,argumentProfiling=com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod.1,sampleInterval=100 -cp target/jvm-profiler-1.0.0.jar com.uber.profiling.examples.HelloWorldApplication
Используйте следующую команду для запуска профилировщика jvm с исполняемым приложением jar.
java -javaagent:/opt/jvm-profiler/target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.ConsoleOutputReporter,metricInterval=5000,durationProfiling=foo.bar.FooAppication.barMethod,sampleInterval=5000 -jar foo-application.jar
Установите профилировщик jvm в CATALINA_OPTS перед запуском сервера Tomcat. Проверьте файл logs/catalina.out на наличие метрик.
export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/opt/jvm-profiler/target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.ConsoleOutputReporter,metricInterval=5000,durationProfiling=foo.bar.FooController.barMethod,sampleInterval=5000"
Используйте следующую команду, чтобы использовать профилировщик jvm с Spring Boot 2.x. Для Spring Boot 1.x используйте -Drun.arguments
вместо -Dspring-boot.run.jvmArguments
в следующей команде.
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-javaagent:/opt/jvm-profiler/target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.ConsoleOutputReporter,metricInterval=5000,durationProfiling=foo.bar.FooController.barMethod,sampleInterval=5000"
Uber JVM Profiler поддерживает отправку показателей в Kafka. Например,
java -javaagent:target/jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.KafkaOutputReporter,metricInterval=5000,brokerList=localhost:9092,topicPrefix=profiler_ -cp target/jvm-profiler-1.0.0.jar com.uber.profiling.examples.HelloWorldApplication
Он отправит метрики в тему Profiler_CpuAndMemory Kafka. Пример показателей см. в нижней части этого документа.
См. публикацию в блоге профилировщика JVM.
Uber JVM Profiler поддерживает следующие функции:
Использование памяти отладки для всех исполнителей приложения Spark, включая память кучи Java, память без кучи, собственную память (VmRSS, VmHWM), пул памяти и пул буферов (направленный/сопоставленный буфер).
Отладка использования ЦП, время сборки мусора для всех исполнителей Spark.
Отладка произвольных методов класса Java (сколько раз они запускаются, сколько времени они тратят). Мы называем это профилированием продолжительности.
Отладка произвольного вызова метода класса Java и отслеживание значения его аргумента. Мы называем это профилированием аргументов.
Выполните профилирование Stacktrack и создайте Flamegraph для визуализации времени процессора, затраченного на приложение Spark.
Метрики ввода-вывода отладки (байты чтения/записи диска для приложения, iowait ЦП для компьютера).
Отладка показателей потоков JVM, таких как общее количество потоков, пиковые потоки, активные/активные потоки и новые потоки.
Агент Java поддерживает следующие параметры, которые можно использовать в командной строке Java, например «-javaagent:agent_jar_file.jar=param1=value1,param2=value2»:
reporter: имя класса для генератора отчетов, например com.uber.profiling.reporters.ConsoleOutputReporter или com.uber.profiling.reporters.KafkaOutputReporter, которые уже реализованы в коде. Вы можете реализовать свой собственный репортер и указать здесь имя.
configProvider: имя класса для поставщика конфигурации, например com.uber.profiling.YamlConfigProvider, которые уже реализованы в коде. Вы можете реализовать свой собственный поставщик конфигурации и указать здесь имя.
configFile: путь к файлу конфигурации, который будет использоваться YamlConfigProvider (если для configProvider установлено значение com.uber.profiling.YamlConfigProvider). Это может быть локальный путь к файлу или URL-адрес HTTP.
тег: обычная текстовая строка, которая будет сообщаться вместе с показателями.
metricInterval: как часто следует собирать и сообщать метрики (в миллисекундах).
periodProfiling: настройте профилирование определенного класса и метода, например com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod. Он также поддерживает подстановочный знак (*) для имени метода, например com.uber.profiling.examples.HelloWorldApplication.*.
аргументПрофилинг: настройка для профилирования аргумента конкретного метода, например com.uber.profiling.examples.HelloWorldApplication.publicSleepMethod.1 («.1» означает получение значения для первого аргумента и отправку в генератор отчетов).
sampleInterval: частота (в миллисекундах) выполнения выборки трассировки стека. Если это значение не установлено или равно нулю, профилировщик не будет выполнять выборку трассировки стека.
ioProfiling: профилировать ли метрики ввода-вывода, может быть true или false.
brokerList: список брокеров при использовании com.uber.profiling.reporters.KafkaOutputReporter.
themePrefix: префикс темы при использовании com.uber.profiling.reporters.KafkaOutputReporter. KafkaOutputReporter отправит метрики в несколько тем с этим значением в качестве префикса для названий тем.
outputDir: выходной каталог при использовании com.uber.profiling.reporters.FileOutputReporter. FileOutputReporter будет записывать метрики в этот каталог.
Параметры могут быть предоставлены в качестве аргументов в команде Java или в файле конфигурации YAML, если вы используете configProvider=com.uber.profiling.YamlConfigProvider. Ниже приведен пример файла конфигурации YAML:
reporter: com.uber.profiling.reporters.ConsoleOutputReporter
metricInterval: 5000
Ниже приведен пример показателей ЦП и памяти при использовании ConsoleOutputReporter или KafkaOutputReporter:
{
"nonHeapMemoryTotalUsed" : 11890584.0 ,
"bufferPools" : [
{
"totalCapacity" : 0 ,
"name" : " direct " ,
"count" : 0 ,
"memoryUsed" : 0
},
{
"totalCapacity" : 0 ,
"name" : " mapped " ,
"count" : 0 ,
"memoryUsed" : 0
}
],
"heapMemoryTotalUsed" : 24330736.0 ,
"epochMillis" : 1515627003374 ,
"nonHeapMemoryCommitted" : 13565952.0 ,
"heapMemoryCommitted" : 257425408.0 ,
"memoryPools" : [
{
"peakUsageMax" : 251658240 ,
"usageMax" : 251658240 ,
"peakUsageUsed" : 1194496 ,
"name" : " Code Cache " ,
"peakUsageCommitted" : 2555904 ,
"usageUsed" : 1173504 ,
"type" : " Non-heap memory " ,
"usageCommitted" : 2555904
},
{
"peakUsageMax" : -1 ,
"usageMax" : -1 ,
"peakUsageUsed" : 9622920 ,
"name" : " Metaspace " ,
"peakUsageCommitted" : 9830400 ,
"usageUsed" : 9622920 ,
"type" : " Non-heap memory " ,
"usageCommitted" : 9830400
},
{
"peakUsageMax" : 1073741824 ,
"usageMax" : 1073741824 ,
"peakUsageUsed" : 1094160 ,
"name" : " Compressed Class Space " ,
"peakUsageCommitted" : 1179648 ,
"usageUsed" : 1094160 ,
"type" : " Non-heap memory " ,
"usageCommitted" : 1179648
},
{
"peakUsageMax" : 1409286144 ,
"usageMax" : 1409286144 ,
"peakUsageUsed" : 24330736 ,
"name" : " PS Eden Space " ,
"peakUsageCommitted" : 67108864 ,
"usageUsed" : 24330736 ,
"type" : " Heap memory " ,
"usageCommitted" : 67108864
},
{
"peakUsageMax" : 11010048 ,
"usageMax" : 11010048 ,
"peakUsageUsed" : 0 ,
"name" : " PS Survivor Space " ,
"peakUsageCommitted" : 11010048 ,
"usageUsed" : 0 ,
"type" : " Heap memory " ,
"usageCommitted" : 11010048
},
{
"peakUsageMax" : 2863661056 ,
"usageMax" : 2863661056 ,
"peakUsageUsed" : 0 ,
"name" : " PS Old Gen " ,
"peakUsageCommitted" : 179306496 ,
"usageUsed" : 0 ,
"type" : " Heap memory " ,
"usageCommitted" : 179306496
}
],
"processCpuLoad" : 0.0008024004394748531 ,
"systemCpuLoad" : 0.23138430784607697 ,
"processCpuTime" : 496918000 ,
"appId" : null ,
"name" : " 24103@machine01 " ,
"host" : " machine01 " ,
"processUuid" : " 3c2ec835-749d-45ea-a7ec-e4b9fe17c23a " ,
"tag" : " mytag " ,
"gc" : [
{
"collectionTime" : 0 ,
"name" : " PS Scavenge " ,
"collectionCount" : 0
},
{
"collectionTime" : 0 ,
"name" : " PS MarkSweep " ,
"collectionCount" : 0
}
]
}
Список всех метрик и соответствующую им информацию можно найти здесь.
Мы можем использовать результаты профилирования Stacktrack для создания Flamegraph для визуализации времени процессора. Используя скрипт Python stackcollapse.py
, следующая команда свернёт выходной файл Stacktrack Profiling json в формат входного файла для создания Flamegraph. Сценарий flamegraph.pl
можно найти на FlameGraph.
python stackcollapse.py -i Stacktrace.json > Stacktrace.folded
flamegraph.pl Stacktrace.folded > Stacktrace.svg
Обратите внимание, что для создания Flamegraph необходимо включить выборку трассировки стека. Чтобы включить его, установите параметр sampleInterval
. Если он не установлен или не равен нулю, профилировщик не будет выполнять выборку трассировки стека.