利用火焰图分析程序性能瓶颈
以前入门如何提升C++程序性能的时候久仰火焰图(FlameGraph)大名, 今天又在如何读懂火焰图?里看到, 便动手尝试了一番, 以此记录.
捕获样本
首先我们要捕捉目标进程的CPU调用堆栈信息样本, 作为分析工具的输入. Mac下可以使用dtrace, Linux下可以使用perf.
工具安装
dtrace不需要手动安装, 但Linux发行版通常不会集成perf工具. 在Arch Linux中利用Pacman安装perf工具:
sudo pacman -S perf
捕获程序运行信息
举个栗子, 我们以99Hz的频率, PID是2063的进程为捕获对象, 包括用户态和核心态, 持续60s, 并生成结果:
perf
sudo perf record -F 99 -p 2063 -g -- sleep 60
sudo perf script > out.perf
dtrace
sudo dtrace -x ustackframes=100 -n 'profile-99 /pid == 2063 && arg1/ { @[ustack()] = count(); } tick-60s { exit(0); }' -o out.user_stacks
生成的结果中包含了CPU调用栈, 在每个片段中运行的时间等信息.
生成火焰图
perf对于复杂程序生成的信息数据量太大且不易阅读, 因此有一位大佬写了一个工具把分析结果可视化为图像, 这就是火焰图FlameGraph.
工具安装
首先需要安装FlameGraph, ArchLinux如果配置了ArchLinuxCN仓库的话也可以直接利用Pacman进行安装, MacOS或其他发行版可以直接克隆源码.
在Arch Linux中利用Pacman安装FlameGraph工具:
sudo pacman -S flamegraph-git
直接克隆源码:
git clone git@github.com:brendangregg/FlameGraph.git
export PATH=$PWD/FlameGraph:$PATH
可视化捕获样本
首先通过FlameGraph自带的脚本将不同工具捕获的运行信心进行预处理.
perf
sudo stackcollapse-perf.pl out.perf > out.folded
dtrace
sudo stackcollapse.pl out.stacks > out.folded
经过处理后, 我们就可以进入最后一步, 也就是生成了. 同样也是一条命令. 利用处理结果生成火焰图:
sudo flamegraph.pl out.folded > 11701.svg
打开目录下生成的SVG图像, 这就是火焰图了.
阅读火焰图
简单来说说通过火焰图能够看出哪些问题. 火焰图纵向为调用栈, 下方为父函数, 上方为子函数, 横向为抓取周期. 因此, 某一函数名横向如果越长, 则CPU在此函数中停留的时间也越长, 以此可以分析得到时间主要花在自身还是某一子函数中, 查找性能瓶颈. 在调用栈的同一层为同一函数. 调用栈层次的颜色仅作区分只用, 颜色深浅和运行状态并没有直接关系.
补充说明
如果你的程序使用Java或Go这些更高级的语言开发, 这样生成的火焰图中可能包含了较多你并不关心的信息, 因此不够直观, 此时可以利用FlameGraph提供的针对Java程序的stackcollapse-jstack, 针对Golang的stackcollapse-go等处理工具. 大家可以参考官方文档.
参考资料
许可协议: CC BY-NC-SA 4.0
本文链接:https://blog.angelmsger.com/利用火焰图分析程序性能瓶颈/