Linuxasync-profiler
Posted 宣之于口
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linuxasync-profiler相关的知识,希望对你有一定的参考价值。
async-profiler
本文涉及的图片取自Profiling JVM Applications in Production
async-profiler
是一个对系统性能影响很少的Java采样分析器,不会存在安全点偏差问题. 它具有特定于HotSpot的API,以收集堆栈跟踪并跟踪内存分配。探查器可与基于HotSpot JVM的OpenJDK,Oracle JDK和其他Java运行时一起使用。
async-profiler
可以跟踪以下类型的事件:
- CPU周期
- 硬件和软件性能计数器,例如高速缓存未命中,分支未命中,页面错误,上下文切换等。
- Java堆中的分配
- 满足的锁定尝试,包括Java对象监视器和ReentrantLocks
一、基本概念
1. JVMTI Agents
某些探查器使用openJDK内部API调用AsyncGetCallTrace(ASGT)便于非安全点收集堆栈跟踪。AsyncGetCallTrace不是官方的JVM API。要使用ASGT,请先创建一个JVMTI Agents
JVMTI(JVM Tool Interface)是JVM提供的一套标准的C/C++编程接口,是实现Debugger、Profiler、Monitor、Thread Analyser等工具的统一基础,在主流Java虚拟机中都有实现。
当我们要基于JVMTI实现一个Agent时,需要实现如下入口函数:
// $JAVA_HOME/include/jvmti.h
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
使用C/C++实现该函数,并将代码编译为动态连接库(Linux上是.so),通过-agentpath
参数将库的完整路径传递给Java进程,JVM就会在启动阶段的合适时机执行该函数。在函数内部,我们可以通过JavaVM指针参数拿到JNI和JVMTI的函数指针表,这样我们就拥有了与JVM进行各种复杂交互的能力。
更多JVMTI相关的细节可以参考官方文档。
2. AsyncGetCallTrace
第一个没有安全点偏差问题的Java sampling profilers
, 用于非安全点收集堆栈跟踪。生成单个线程的堆栈,而无需等待安全点。
二、分析
1. CPU profiling
在这种模式下,profiler 收集堆栈跟踪示例,其中包括Java方法、native调用、JVM代码和内核函数。
为了能够准确的生成Java和native代码的确切性能报告,常用的方法是接收perf_events
生成的调用堆栈,并将它们与AsyncGetCallTrace
生成的调用堆栈进行匹配。此外Async-profiler还提供了一种可以在AsyncGetCallTrace失败的某些情况下,恢复堆栈跟踪的解决方法
2. ALLOCATION profiling
async-profiler
不使用侵入性技术,例如字节码检测工具或昂贵的DTrace探针,这些技术会对性能产生重大影响。它也不会影响转义分析或防止JIT优化, 如分配消除。仅测量实际堆分配.
探查器具有TLAB驱动的采样功能。它依赖于HotSpot特定的回调来接收两种通知:
- 在新创建的TLAB中分配对象时(火焰图中的浅绿色帧)
- 当在TLAB之外的慢路径上分配对象时(棕色框架)
这意味着不对每个分配进行计数,而仅对每N kB进行分配,其中N是TLAB的平均大小。这使得堆采样非常便宜并且适合于生产。另一方面,收集的数据可能不完整,尽管在实践中通常会反映出最主要的分配来源
采样间隔可以通过-i
选件进行调整。例如,-i 500k
平均分配500 KB的空间后,将采样一个样本。但是,小于TLAB大小的间隔不会生效。
三、与perf对比
1. perf
- 仅支持Java 8u60及更高版本(以禁用FPO)
- 禁用FPO对性能有较小的影响(在极端情况下最高可达10%)
- 方法名解析需要映射(map)文件:
perf-map-agent
- 不支持
interpreter frames
- 堆栈深度通常限制为127 - 从Linux 4.8开始可以使用:
/proc/sys/kernel/perf_event_max_stack
- 支持系统范围内的分析
2. async-profiler
与直接将perf_events
与Java代理一起使用相比较,该方式具有以下优点:
- 它适用于较旧的Java版本,因为它不需要
-XX:+PreserveFramePointer
,这个参数只在JDK 8u60和更高版本中可用 - 不需要引入
-XX:+PreserveFramePointer
,因为它可能导致较高的性能开销,在极少数情况下可能高达10% - 不需要生成映射文件来将Java代码地址映射到方法名
- 可以与
interpreter frames
一起工作 - 不需要为了后续的进一步分析而需要生成perf.data文件
四、使用教程
1. 安装
$ git clone https://github.com/jvm-profiling-tools/async-profiler
$ cd async-profiler
$ make
2. 参数
./profiler.sh [action] [options] <pid>
部分参数:
# Actions
start/stop # 开始分析/结束分析
list # 显示可用分析事件的列表。此选项仍然需要PID,因为受支持的事件可能因JVM版本而异
# Options
-d N # 分析持续时间
-e event # cpu, alloc, lock, cache-misses etc
-f filename # 将配置文件信息转储到的文件名 <filename>
3. 使用
a. 程序运行时动态载入
启动Java应用程序,然后使用代理开始分析,收集性能情况然后停止分析
$ jps
9234 Jps
8983 Computey
$ ./profiler.sh start 8983
$ ./profiler.sh stop 8983
或者可以通过 -d
指定分析时间
$ ./profiler.sh -d 30 8983
b. 作为代理启动
如果您需要在JVM启动后立即配置一些代码,而不是使用profiler.sh
脚本,则可以在命令行上附加async-profiler
作为代理。例如:
$ java -agentpath:/path/to/libasyncProfiler.so=start,file=profile.svg ...
4. 火焰图可视化
async-profiler
提供了开箱即用的火焰图支持。指定-o svg
参数以将分析结果转储为交互式SVG,可在所有主流浏览器中立即查看。另外,如果目标文件名以结尾,则会自动选择SVG输出格式.svg
。
$ jps
9234 Jps
8983 Computey
$ ./profiler.sh -d 30 -f /tmp/flamegraph.svg 8983
五、实验
本实验参照该实验手册:linux-tracing-workshop
Task 1: Profiling Java Code
首先,运行我们将要分析的Java应用程序。 它是同一主要计数应用程序的Java版本:
$ java slowy/App
Press ENTER to start.
暂时不要按ENTER
, 在另一个shell中运行jps
找到Slowy应用程序的进程ID
$ jps
6043 App
6076 Jps
然后运行收集工具之后,在Java应用程序的控制台中按ENTER,以便收集工具记录一些有意义的工作
# 进入 目录
./profiler.sh -d 15 6043
默认情况下,分析频率为100Hz(每10ms CPU时间)这是打印到Java应用程序终端的输出示例,显示Java程序中的瓶颈:slowy.App.isPrime
,导致该方法的最热的调用堆栈来slowy.App.main
Started [cpu] profiling
--- Execution profile ---
Total samples : 376
Frame buffer usage : 0.0035%
--- 3729803417 ns (99.20%), 373 samples
[ 0] slowy.App.isPrime
[ 1] slowy.App.main
--- 10213575 ns (0.27%), 1 sample
[ 0] finish_task_switch_[k]
[...]
ns percent samples top
---------- ------- ------- ---
3729803417 99.20% 373 slowy.App.isPrime
10213575 0.27% 1 finish_task_switch_[k]
10013086 0.27% 1 Symbol::operator new(unsigned long, int, Arena*, Thread*)
9997484 0.27% 1 slowy.App.main
Task 2: Flame Graph visualization
同样运行Java application, 并查看pid
$ jps
6841 Jps
6827 App
然后可以直接利用该命令,输出火焰图:
./profiler.sh -d 15 -f /tmp/flamegraph.svg 6827
ps: async-profiler 支持容器,perf 不支持,待验证
参考文档:
2. Java应用性能分析工具:async-profiler
5. Basics on profiling JVM in Linux
以上是关于Linuxasync-profiler的主要内容,如果未能解决你的问题,请参考以下文章
2020-2021年顶会上关于解决偏差(bias)问题的文献整理