perf快速起步¶
备注
本文仅是一个快速实践记录,我对性能观测理解不深,需要不断学习和实践。会持续改进文档,补充内容。
perf实现原理¶
perf的原理是每隔固定时间,在CPU上(每个cpu核心)产生一个中断,在中断上看当前是哪个pid和哪个函数,然后给对应的pid和函数加上一个统计值。这样我们就能够知道CPU有百分之几的时间在某个pid或者某个函数了
perf stat¶
perf stat
提供了性能统计数据,可以指定进程进行观察:
perf stat -p 103314
过一段时间按下 ctrl-c
退出perf,就可以看到统计信息:
Performance counter stats for process id '103314':
856,089.63 msec task-clock # 10.327 CPUs utilized
1,121,134 context-switches # 1309.600 M/sec
171,867 cpu-migrations # 200.758 M/sec
214,445 page-faults # 250.494 M/sec
1,563,545,050,590 cycles # 1826381.428 GHz (83.21%)
148,330,561,668 stalled-cycles-frontend # 9.49% frontend cycles idle (83.37%)
196,549,357,979 stalled-cycles-backend # 12.57% backend cycles idle (83.39%)
1,595,812,172,679 instructions # 1.02 insn per cycle
# 0.12 stalled cycles per insn (83.45%)
375,183,700,209 branches # 438253149.157 M/sec (83.50%)
3,660,917,377 branch-misses # 0.98% of all branches (83.11%)
82.895081792 seconds time elapsed
perf记录和火焰图¶
对应用进程进行perf记录:
sudo perf record -F 99 -p 504843 -g -- sleep 60
参数说明:
-F 99
: 每秒采样99次 - 使用99而不是100,是为了防止采样周期与某些系统周期事件重合,影响采样结果sleep 60
: 持续采样60秒-g
: 记录调用栈-p 504843
: 进程号,表示对哪个进程进行分析
CPU核心数量越多,则采样记录的调用栈就越多
上述命令执行结束以后,会在 /tmp
目录下生成一个 perf.data
文件
执行分析可以使用
perf report
命令统计:sudo perf report -n --stdio
统计出每个调用栈出现百分比,从高到低排序。不过这个输出不是很容易观察
火焰图¶
dump出perf.data内容:
sudo perf script > out.perf
下载火焰图工具:
git clone --depth 1 https://github.com/brendangregg/FlameGraph.git
折叠调用栈:
FlameGraph/stackcollapse-perf.pl out.perf > out.folded
生成火焰图:
FlameGraph/flamegraph.pl out.folded > out.svg
生成火焰图可以指定参数, –width
可以指定图片宽度, –height
指定每一个调用栈的高度;还可以针对语言设置火焰图颜色,例如 --color=js
是针对JavaScript配色svg, --color=java
则是针对Java配色svg。
上述两个生成火焰图的命令步骤也可以合并成一个命令:
FlameGraph/stackcollapse-perf.pl < out.perf | FlameGraph/flamegraph.pl out.folded > out.svg
其他的案例命令:
FlameGraph/stackcollapse-perf.pl --kernel < out.perf | FlameGraph/flamegraph.pl --color=js --hash > out.svg
综合步骤¶
如果对系统进行观察,可以将上述火焰图数据采集和操作步骤合并成以下命令:
git clone https://github.com/brendangregg/FlameGraph
cd FlameGraph
perf record -F 99 -a -g -- sleep 60
perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > out.svg
火焰图观察简介¶
火焰图的Y轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方就是该函数的父函数。
火焰图的X轴表示抽样数量,如果一个函数在X轴占据的宽度越款,就表示它被抽到的次数越多,即执行的时间越长。
注意:X轴不代表时间,而是所有调用栈合并以后按照字母顺序排列的
火焰图就是看顶层哪个函数占据的宽对最大。只要有 ``平顶`` (plateaus) 就表示该函数存在性能问题。
火焰图的颜色没有特殊含义,只是表示CPU的繁忙程度,一般选择暖色调。
鼠标放到一个函数上后, 会展示完整的函数名, 被抽样中的次数, 占总抽样次数的百分比
点击某个函数后, 该函数会水平放大到占据整个页面, 展示详细信息
点击左上角
Reset Zoom
恢复缩放ctrl + f
可以搜索关键词或正则, 所有符合的函数名会高亮显示
火焰图局限性¶
有两种情况无法画出火焰图,需要修正系统行为:
调用栈不完整: 当调用栈过深时,某些系统只返回前面一部分(例如前10曾)。
函数名缺失: 有些函数没有名字,编译器只是用内存地址来表示(例如匿名函数)。