性能测试——火焰图
0. perf 简介
Perf 是一个用于访问处理器性能监视单元 (PMU) 以及记录和显示软件事件(例如页错误)的界面。它支持系统范围的监视、按线程的监视和 KVM 虚拟化 Guest 监视。
可以在报告中储存生成的信息。例如,此报告包含有关指令指针的信息,或线程执行的代码的信息。
Perf 由两部分组成:
- 集成到 Linux 内核的代码,负责向硬件发出指令。
- perf 用户空间实用程序,可让您使用内核代码并帮助您分析收集的数据。
1. 安装 perf
cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
sudo yum install perf
...
2. perf 的使用
2.1 perf 分析流程
Perf 进行性能分析的方式通常有两种:
- 使用 perf stat 等命令对特定的事件计数器进行计算,并在程序结束后打印数值
- 使用 perf record 等命令以若干的事件为触发间隔对系统进行采样,将数据保存至 perf.data 文件以供后续分析
- 也就是说,perf stat 命令只能记录事件发生的次数,perf record 在此基础之上可以记录事件发生时详细的数据(比如 IP、堆栈等等)。
perf record 流程图:
在虚拟机上演示:
perf stat ls
Performance counter stats for 'ls':
1.643793 task-clock (msec) # 0.750 CPUs utilized
0 context-switches # 0.000 K/sec
0 cpu-migrations # 0.000 K/sec
265 page-faults # 0.161 M/sec
<not supported> cycles
<not supported> instructions
<not supported> branches
<not supported> branch-misses
0.002190790 seconds time elapsed
perf record ls
perf.data
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.016 MB perf.data (7 samples) ]
2.2 perf 事件支持
通过 perf list 可以查看当前支持的所有时间包括硬件事件、软件事件、硬件cache事件、PMU事件以及预设Tracepoint事件
2.3 perf stat(统计特定类型的事件)
要统计某个事件(例如 perf list 显示的事件)的发生次数,请使用:
perf stat -e EVENT -a
要一次性统计多种类型的事件,请列出这些事件并以逗号分隔。例如,要统计 cpu-cycles 和 instructions,请使用:
perf stat -e cpu-cycles,instructions -a
要停止会话,请按 Ctrl+C。
还可以统计某个事件在特定时间范围内发生的次数:
perf stat -e EVENT -a -- sleep TIME
请将 TIME 替换为以秒为单位的值。
2.4 perf record(记录特定于特定命令的事件)
1、可通过各种方式来对特定于特定命令的事件采样:
1)要创建新调用的命令的报告,请使用:
perf record COMMAND
然后正常使用启动的进程。退出该进程时,Perf 会话也会停止。
2)要在运行新调用的命令时创建整个系统的报告,请使用:
perf record -a COMMAND
3)要创建已运行的进程的报告,请使用:
perf record -p PID
请将 PID 替换为进程 ID。要停止会话,请按 Ctrl–C。
2、现在,可使用以下命令查看收集到的数据 (perf.data):
perf report
这会打开一个伪图形界面。要获得帮助,请按 H。要退出,请按 Q。
3、如果您偏向于使用图形界面,请尝试 Perf 的 GTK+ 界面:
perf report --gtk
但请注意,GTK+ 界面的功能很有限。
火焰图
火焰图是用图形化的方式来展现perf等工具采集的性能数据,对数据进行统计和分析,方便找出性能热点。
git clone https://github.com/brendangregg/FlameGraph.git
在 GitHub 项目:FlameGraph 主页有生成火焰图的详细说明。
克隆项目:
git clone https://github.com/brendangregg/FlameGraph.git
一个实例:
1.st 生成 perf.data
perf record -F 99 -a -g -- sleep 60
上述代码中 perf record 表示记录,
-F 99 表示每秒99次,
-p 13204 是进程号,即对哪个进程进行分析,
-g 表示记录调用栈,
sleep 30 则是持续30秒,-a 表示记录所有cpu调用。更多参数可以执行
这条指令的意思是,对CPU所有进程以 99Hz 采集,它的执行频率是 99Hz(每秒99次),如果 99 次都返回同一个函数名,那就说明 CPU 这一秒钟都在执行同一个函数,可能存在性能问题。执行60秒后会弹出如下图提示表示采集完成,在当前目录会生成一个perf.data的文件。
perf.data 文件生成后,表示采集完成。最好是在火焰图的目录下进行采集,方便转换成SVG图形。
2.st 生成火焰图
//生成脚本文件
perf script -i perf.data &> perf.unfold
//生成火炬图
./FlameGraph/stackcollapse-perf.pl perf.unfold &> perf.folded
./FlameGraph/flamegraph.pl perf.folded > perf.svg
执行完成后生成 perf.svg 图片,可以下载到本地,用浏览器打开 perf.svg,如下图
火焰图的含义
火焰图是基于 perf 结果产生的 SVG 图片,用来展示 CPU 的调用栈。
y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。
x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。
火焰图就是看顶层的哪个函数占据的宽度最大。只要有”平顶”(plateaus),就表示该函数可能存在性能问题。
颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调。
差分火焰图
# 第一次Profiling结果
perf record -ag -F 999 -- sleep 20
perf script -i perf.data &> A.stacks
# 第二次Profiling结果
perf record -ag -F 999 -- sleep 20
perf script -i perf.data &> B.stacks
# 下载FlameGraph仓库
git clone --depth 1 http://github.com/brendangregg/FlameGraph
# 折叠A.stacks和B.stacks
./FlameGraph/stackcollapse-perf.pl A.stacks &> A.folded
./FlameGraph/stackcollapse-perf.pl B.stacks &> B.folded
# 基于折叠结果做差
./FlameGraph/difffolded.pl A.folded B.folded > diff.folded
# 生成差分火焰图
./FlameGraph/flamegraph.pl diff.folded > diff.svg
参考资料: