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

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/利用火焰图分析程序性能瓶颈/