为什么要做性能分析
很多场景的 Java 应用中 IT 成本中 CPU 成本常常是成本的大头,如果能够有效优化 Java 应用的 CPU 占用,可以较好降低成本,提升程序响应速度。
Java 性能分析分为两部分
- 业务性能:某些的业务代码引起的性能瓶颈
- JVM 性能调优:JVM 设置存在优化
本文主要关注业务代码的热点问题。
Arthas 是什么?
Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。
当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
本文主要介绍如何利用 profiler
命令来定位应用热点,从而优化应用的性能。
为什么选择 Arthas 来做火焰图?
Arthas 无需代理模式启动应用,通过 Attach 进程方式即可实现 Java 应用的诊断与性能分析。
详细可以参考:Arthas 原理分析
Java 火焰图在 Netflix 的加持下,逐渐成熟, async-profile 出现后进一步降低了对 Java 火焰图的分析步骤。
Arthas 在 3.1.5 版本开始支持 async-profile
, 无需配置,快速实现 profile 分析。
使用 Arthas 生成火焰图
安装和启动 Arthas
全量安装arthas
是一个 jar
包,下载后直接运行即可,然后执行相应命令。
1 |
|
创建火焰图
启动 arthas 后,attach 到实际的进程
1 | ➜ arthas java -jar arthas-boot.jar |
注意: 输入前面的序号 1
不是 724
使用 profiler
命令
1 | # 启动 |
本机可以通过 http://localhost:3658/arthas-output/
直接查看结果
也可以通过 Chrome
打开 output.svg
文件
点击某个函数调用栈可以看到放大局部的调用栈,最新 3.28%
是 CPU 占比。
点击 all
返回默认的全局展示。
容器内使用
由于 k8s
的 perf_event_open
默认是未开启的状态,在容器内使用会有权限问题。
观察日志会发现:
1 | perf_event_open failed: Permission denied |
此时可以使用 itimer
事件来采样,此事件与 cpu
采样类似,但是不需要 perf_events
支持,缺点是无法统计内核的堆栈性能。通过 --event
可以指定
1 | # 使用 itimer 采样 |
其他问题可以参考:async-profiler#troubleshooting
看懂火焰图
Y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。
X 轴表示抽样数,如果一个函数在x轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。
火焰图就是看顶层的哪个函数占据的宽度最大。只要有平顶 (plateaus),就表示该函数可能存在性能问题。
颜色没有实际意义,只是随机选取用于栈帧之间相互区分,左右顺序也没有什么含义。