火焰图(Flame Graph)性能分析工具使用指南
火焰图(Flame Graph)作为一款强大的可视化性能分析工具,能帮助我们快速定位CPU、内存或I/O方面的瓶颈问题,让性能优化工作变得更加高效。今天就来给大家详细讲讲火焰图的使用方法。
一、火焰图能解决哪些问题?
- CPU占用高:当我们遇到CPU占用过高的情况时,火焰图可以清晰地展示出哪些函数消耗了最多的CPU时间,让我们能快速锁定问题函数。
- 程序卡顿:它能深入分析代码的执行路径,帮我们找到那些导致程序运行缓慢的慢速操作,进而优化程序性能。
- 线程阻塞:火焰图还能查看哪些线程在等待锁或者I/O资源,方便我们排查线程阻塞问题,提高程序的并发性能。
- 内存泄漏(需配合内存分析工具):虽然火焰图不能单独检测内存泄漏,但配合其他内存分析工具,它可以在内存性能分析方面发挥重要作用。
二、使用火焰图前的准备工作(Linux / macOS系统)
(一)安装perf(Linux性能分析工具)
在不同的Linux发行版中,安装perf的命令有所不同:
- Ubuntu/Debian系统:在终端输入
sudo apt install linux-tools-common linux-tools-generic
。这条命令会安装perf工具及其相关依赖,sudo
表示以管理员权限运行,apt
是Ubuntu/Debian系统的包管理工具,install
用于安装软件包。 - CentOS/RHEL系统:使用
sudo yum install perf
命令进行安装。yum
是CentOS/RHEL系统的包管理工具,同样通过sudo
获取管理员权限来安装perf。
(二)安装FlameGraph脚本
FlameGraph脚本是生成火焰图的关键工具,我们可以通过Git来获取它:
- 在终端执行
git clone https://github.com/brendangregg/FlameGraph.git
。这条命令会从指定的GitHub仓库克隆FlameGraph项目到本地。 - 进入克隆下来的FlameGraph目录:
cd FlameGraph
。 - 将FlameGraph目录临时添加到系统的PATH环境变量中,执行
export PATH=$PATH:$(pwd)
。这样,系统就能在当前目录下找到相关的脚本文件,方便后续生成火焰图。
三、生成CPU火焰图(以Java为例)
(一)采集数据
- 方法1:使用perf(推荐,适用于Linux)
- 找到Java进程ID:可以使用
jps
命令,如果系统没有安装jps
,也可以用ps -ef | grep java
命令来查找Java进程的ID。这两个命令的作用都是在系统进程列表中找到正在运行的Java进程,并显示其进程ID。 - 采集CPU调用栈(采样30秒):在终端输入
sudo perf record -F 99 -p -g -- sleep 30
。这里sudo
获取管理员权限,perf record
用于记录性能数据,-F 99
表示每秒采样99次,-p
后面需要跟上前面查到的Java进程ID,-g
表示记录调用栈信息,-- sleep 30
表示采样持续30秒。 - 生成火焰图:执行
perf script | stackcollapse-perf.pl | flamegraph.pl > flamegraph.svg
。这条命令通过管道操作,将perf script
采集到的数据依次经过stackcollapse-perf.pl
和flamegraph.pl
脚本处理,最终生成名为flamegraph.svg
的火焰图文件。
- 找到Java进程ID:可以使用
- 方法2:使用async-profiler(更简单,支持Java)
- 下载async-profiler:在终端执行
wget https://github.com/jvm-profiling-tools/async-profiler/releases/download/v2.9/async-profiler-2.9-linux-x64.tar.gz
,这条命令会从指定的GitHub发布页面下载async-profiler
的压缩包。然后解压压缩包,执行tar -xzf async-profiler-.tar.gz
,并进入解压后的目录:cd async-profiler-
。 - 采集CPU数据(采样30秒):在解压后的目录下执行
./profiler.sh -d 30 -f flamegraph.svg
。-d 30
表示采样时间为30秒,-f flamegraph.svg
指定生成的火焰图文件名为flamegraph.svg
。
- 下载async-profiler:在终端执行
(二)查看火焰图
生成的flamegraph.svg
文件可以用浏览器打开,比如使用firefox flamegraph.svg
,当然也可以用Chrome、Edge等其他浏览器打开,这样就能直观地查看火焰图了。
四、如何读懂火焰图?
(一)火焰图结构
- Y轴(高度):代表调用栈深度,越往火焰图的下方,调用链就越长。就好比一个函数调用了其他函数,其他函数又继续调用别的函数,调用链不断延伸,在火焰图上就体现为Y轴方向的深度增加。
- X轴(宽度):表示函数执行时间占比,函数在X轴上显示得越宽,说明它占用的CPU时间越多,也就意味着这个函数可能是导致性能问题的关键所在。
- 颜色:火焰图中的颜色并没有特殊含义,只是为了区分不同的函数,让我们在查看火焰图时能更清晰地分辨各个函数。
(二)关键操作
- 鼠标悬停:当我们把鼠标悬停在火焰图的某个函数区域上时,会显示出该函数的名称以及它占用CPU的比例,方便我们快速了解函数的基本信息。
- 点击放大:点击火焰图中的某个函数区域,可以放大查看这个函数的详细调用链,深入分析函数内部的调用情况,找出可能存在的性能问题。
- 搜索(Ctrl+F):如果我们想查找特定的函数,比如
java.lang.Thread.sleep
,可以使用浏览器的搜索功能(一般是按下Ctrl+F组合键),在火焰图中快速定位到目标函数。
五、常见问题及解决方法
(一)火焰图显示[unknown]怎么办?
- 原因:出现这种情况通常是因为缺少调试符号,比如JVM没有启用
-XX:+PreserveFramePointer
参数。这个参数用于保留函数调用栈的指针信息,没有它,火焰图可能无法准确识别函数。 - 解决方案:
- Java运行时添加参数:在运行Java程序时添加
-XX:+PreserveFramePointer
参数,例如java -XX:+PreserveFramePointer -jar your_app.jar
。这样JVM在运行时就会保留相关指针信息,有助于火焰图准确识别函数。 - 使用async-profiler的–all-user选项:使用
async-profiler
采集数据时,添加--all-user
选项,命令为./profiler.sh --all-user -d 30 -f flamegraph.svg
。这个选项可以让async-profiler
采集更多用户空间的信息,提高函数识别的准确性。
- Java运行时添加参数:在运行Java程序时添加
(二)如何分析内存泄漏?
如果要分析内存泄漏问题,可以改用内存火焰图(需借助async-profiler
) 。在async-profiler
的目录下执行./profiler.sh -d 30 -e alloc -f mem_flamegraph.svg
。-e alloc
表示以内存分配事件为采样依据,-d 30
还是采样30秒,-f mem_flamegraph.svg
指定生成的内存火焰图文件名为mem_flamegraph.svg
。通过分析这个内存火焰图,我们可以更直观地了解内存的分配情况,从而发现可能存在的内存泄漏问题。
六、进阶用法
- 分析锁竞争:在
async-profiler
目录下执行./profiler.sh -e lock -d 30 -f lock.svg
。-e lock
表示以锁竞争事件为采样依据,采样30秒后生成名为lock.svg
的火焰图,通过这个火焰图可以分析程序中的锁竞争情况,找出可能导致线程阻塞的锁。 - 分析I/O等待:在终端执行
perf record -e 'sched:sched_stat_iowait' -p -g -- sleep 10
。这里-e 'sched:sched_stat_iowait'
指定以I/O等待事件为采样依据,-p
跟上目标进程ID,-g
记录调用栈信息,-- sleep 10
表示采样10秒。通过这种方式采集的数据生成的火焰图,可以帮助我们分析I/O等待问题。 - 生成差分火焰图:如果我们想对比两个不同状态下的火焰图差异,可以使用
diff two_flamegraphs.svg
命令。这里two_flamegraphs.svg
需要替换为实际要对比的两个火焰图文件名,通过查看差分火焰图,我们能更清楚地看到两次采样之间的性能变化。
七、总结
- 安装工具:可以选择安装
perf + FlameGraph
组合,或者使用async-profiler
工具,它们都能帮助我们生成火焰图。 - 采集数据:使用
perf record
命令或者async-profiler
的./profiler.sh -d 30
命令来采集性能数据,采样时间可以根据实际情况调整。 - 生成SVG:利用
flamegraph.pl
脚本对采集到的数据进行转换,最终生成可供查看分析的火焰图文件(.svg
格式)。
希望通过这篇文章,大家能对火焰图的使用有更深入的了解,在实际工作中借助火焰图更好地进行性能优化。