使用火焰图分析程序性能
火焰图是对层次数据的可视化。 我们通常可以将性能分析工具采集到的调用栈信息以火焰图的方式进行可视化。 从而直观且准确地观察到频繁调用的代码路径。
perf
perf
是 Linux 系统上的性能分析工具。
perf
可以周期性地产生中断,在中断处理中获取并记录当前调用栈信息。
安装 perf
:
dnf install perf
perf --version
BCC
BCC(BPF Compiler Collection)是用于创建内存跟踪与操作程序的工具包,依赖 eBPF。
我们这里只需要使用它提供的 offcputime
工具,用于采集 off-CPU 的时间与堆栈信息。
dnf install bcc
/usr/share/bcc/tools/offcputime --help
如果执行报错说找不到内核头文件,就需要安装正确版本的 kernel-devel
依赖包:
dnf install kernel-devel-"$(uname -r)"
FlameGraph 工具
FlameGraph 以 perf
采集到的调用栈数据为输入,生成火焰图。
不需要安装,直接 clone 即可:
git clone https://github.com/brendangregg/FlameGraph.git
CPU 火焰图
https://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html
CPU 火焰图用于分析 CPU 繁忙的原因,通过调用栈分析找到热点代码路径。 一般是以固定频率对运行中的程序状态进行采样,将采集到的数据转化为火焰图。 通常的采样分析可以创建定时中断,每次中断时采集当前的 PC 寄存器、函数地址、调用栈等信息。 注意一下,CPU 火焰图是用于 on-CPU 分析的,分析的范围是程序花费的 CPU 时间,不涉及 I/O、锁、换页等阻塞时间。
首先我们把工作路径切到 clone 下来的 FlameGraph 里面。
cd FlameGraph
然后可通过 perf record
命令采集调用栈数据,下面提供的命令会将采集结果输出到 perf.data
中:
perf record -F <frequency> -a -g -p <pid> -- <cmd>
perf record -F 99 -a -g -p "$(pgrep -x mysqld -u <username>)" -- mysql -e "select * from <some-table>"
perf record -F 99 -a -g -p "$(pgrep -x mysqld -u <username>)" -- sleep 30"
最后通过 FlameGraph 工具生成火焰图。
示例中输出的文件名是 mysqld-on-cpu.svg
。
这个 .svg
文件可直接用浏览器打开。
perf script | ./stackcollapse-perf.pl > out.perf-folded
cat out.perf-folded | ./flamegraph.pl > mysqld-on-cpu.svg
Off-CPU 火焰图
https://www.brendangregg.com/offcpuanalysis.html
Off-CPU 分析是指通过通过 off-CPU 的时间与调用栈信息确定线程阻塞的原因,它的分析范围是程序花费在等待 I/O、锁、换页等阻塞的时间。
线程离开 CPU 的原因很多,除了主动等待 I/O 与锁之外,还有一些与线程本身无关的原因,比如中断处理,在 CPU 资源紧张情况下的上下文切换等。
首先工作路径仍然是 FlameGraph 的项目目录:
cd FlameGraph
然后通过 offcputime
命令测量阻塞时间与调用栈信息:
/usr/share/bcc/tools/offcputime -df -p `pgrep -x mysqld -u <username>` 30 > out.stacks
最后使用 FlameGraph 工具生成冷火焰图:
./flamegraph.pl --color=io --title="Off-CPU Time Flame Graph" --countname=us < out.stacks > mysqld-off-cpu.svg