利用火焰图分析程序性能瓶颈

Author Avatar
AngelMsger 1月 02, 2018

以前入门如何提升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等处理工具。大家可以参考官方文档。

参考资料

  1. 如何读懂火焰图?
  2. brendangregg/FlameGraph

许可协议: CC BY-NC-SA 4.0
本文链接:https://blog.angelmsger.com/利用火焰图分析程序性能瓶颈/