C++ 之 perf+ 火焰图分析与调试
简介
在遇到一些内存异常的时候,经常这部分的代码是很难去进行分析的,最近了解到 Perf 这个神器,这里也展开介绍一下如何使用 Perf 以及如何去画火焰图。
1. Perf 基础
1.1 Perf 简介
perf 是 Linux 下的一款性能分析工具,能够进行函数级与指令级的热点查找。利用 perf 剖析程序性能时,需要指定当前测试的性能时间。性能事件是指在处理器或操作系统中发生的,可能影响到程序性能的硬件事件或软件事件
1.2 Perf 的安装
ubuntu 18.04:
1.3 perf 命令简要介绍
perf list
perf list
主要是用于列出有哪些可用的 event,可以供 perf top -e eventname
来分析。perf list [hw|sw|cache|tracepoint|pmu|event_glob]
,其中perf list hw
可以列出 hard ware 的 event, sw 是 software 的 event, 其它类似。
hw/hardware 显示支持的硬件事件相关,如: perf list hardwaresw/software 显示支持的软件事件列表: perf list swcache/hwcache 显示硬件 cache 相关事件列表: perf list cachepmu 显示支持的 PMU 事件列表: perf list pmutracepoint 显示支持的所有 tracepoint 列表,这个列表就比较庞大: perf list tracepoint
perf top
perf top 的作用是实时显示系统/进程的性能统计信息,上面的 perf list [hw|sw...]
可以知道所有的 tracepoint events, 接下来我们就可以使用 perf top -e tracepoint-event
来专门获得指定的 tracepoint 的信息。其中常用的常用参数有
-e:指定性能事件-a:显示在所有 CPU 上的性能统计信息-C:显示在指定 CPU 上的性能统计信息-p:指定进程 PID-t:指定线程 TID-K:隐藏内核统计信息-U:隐藏用户空间的统计信息-s:指定待解析的符号信息‘‐G’ or‘‐‐call‐graph’ <output_type,min_percent,call_order>
perf top -e cpu-clock
: 查看 CPU 的使用!
perf top -p 28764
:查看对应 PID 的使用
注:perf−top 需要 root 权限
perf stat
启动应用程序并分析该程序完整生命周期的性能状况。虽然perf top
也可以指定 pid,但是对于perf top
而言必须先启动应用才能查看信息。perf stat
能够运行指令,并且能完整统计应用整个生命周期的信息。其中默认统计 8 种 event 在程序运行过程中的计数,如下所示。也可以使用-e 选项来自定义使用的 event。
task‐clock 事件表示目标任务真正占用处理器的时间,单位是毫秒。也称任务执行时间
context-switches
是系统发生上下文切换的次数CPU-migrations
是任务从一个处理器迁往另外一个处理器的次数page-faults
是内核发生缺页的次数cycles
是程序消耗的处理器周期数instructions
是指命令执行期间产生的处理器指令数branches
是指程序在执行期间遇到的分支指令数。branch‐misses
是预测错误的分支指令数。XXX seconds time elapsed
系程序持续时间任务执行时间/任务持续时间大于 1,那可以肯定是多核引起的
参数设置:
-e:选择性能事件
-i:禁止子任务继承父任务的性能计数器。-r:重复执行 n 次目标程序,并给出性能指标在 n 次执行中的变化范围。-n:仅输出目标程序的执行时间,而不开启任何性能计数器。-a:指定全部 cpu-C:指定某个 cpu-A:将给出每个处理器上相应的信息。-p:指定待分析的进程 id-t:指定待分析的线程 id
perf record&perf report
使用perf record
和perf report
命令来进行更详细的分析:
perf stat
命令只能记录 event 发生的次数,perf record
在此基础之上可以记录 event 发生时详细的数据(比如 IP、堆栈等等)。可以自定义需要记录的 event,可以自定义记录数据的格式。perf record
可以记录一段时间内系统/进程的性能时间,具体参数为:
-e:选择性能事件
-p:待分析进程的 id
-t:待分析线程的 id
-a:分析整个系统的性能
-C:只采集指定 CPU 数据-c:事件的采样周期
-o:指定输出文件,默认为 perf.data
-A:以 append 的方式写输出文件
-f:以 OverWrite 的方式写输出文件
-g:记录函数间的调用关系-F:采样评率,采样频率建议在 4000 以内,避免造成太多开销
perf report
可以读取perf record
生成的数据文件,并显示分析数据参数
-i:输入的数据文件-v:显示每个符号的地址-d :只显示指定 dos 的符号-C:只显示指定 comm 的信息(Comm. 触发事件的进程名)-S:只考虑指定符号-U:只显示已解析的符号-g[type,min,order]:显示调用关系,具体等同于 perf top 命令中的-g-c:只显示指定 cpu 采样信息-M:以指定汇编指令风格显示 –source:以汇编和 source 的形式进行显示-p:用指定正则表达式过滤调用函数
性能调优时,我们通常需要分析查找到程序百分比高的热点代码片段,这便需要使用 perf record
记录单个函数级别的统计信息,并使用 perf report
来显示统计结果;
首先我们用以下命令模拟出 CPU 利用率暴涨的现象:
然后我们看到 CPU 1 的 %system 飙升到 95%:
现在我们用 perf 工具采样:
把采样的数据生成报告:
我们很清楚地看到,CPU 利用率有 75%来自 cat 进程 的 sys_read 系统调用,perf 甚至精确地告诉了我们是消耗在 read_zero 这个 kernel routine 上。
值得说明的是perf record
默认只使用了 1 种 event cpu-clock
,cpu-clock 使用的是高精度定时器来进行定时采样。perf record
默认数据输出文件为 perf.data。
2. 火焰图
2.1 火焰图简介
火焰图(Flame Graph)是由 Linux 性能优化大师 Brendan Gregg 发明的,Flame Graph 以一个全局的视野来看待时间分布,它从底部往顶部,列出所有可能的调用栈。其他的呈现方法,一般只能列出单一的调用栈或者非层次化的时间分布。
2.2 火焰图含义:
y 轴表示调用栈, 每一层都是一个函数. 调用栈越深, 火焰就越高, 顶部就是正在执行的函数, 下方都是它的父函数.
x 轴表示抽样数, 如果一个函数在 x 轴占据的宽度越宽, 就表示它被抽到的次数多, 即执行的时间长. 注意, x 轴不代表时间, 而是所有的调用栈合并后, 按字母顺序排列的。
火焰图就是看顶层的哪个函数占据的宽度最大. 只要有 “平顶”(plateaus), 就表示该函数可能存在性能问题。
颜色没有特殊含义, 因为火焰图表示的是 CPU 的繁忙程度, 所以一般选择暖色调.
2.3 火焰图安装
安装 FlameGraph
添加到 bashrc 环境变量
查找程序的 pid
火焰图生成脚本
然后启动 bash 文件并传入 pid
火焰图可以使用浏览器来打开
X 轴是 CPU 时间,色块越宽,表示对应函数占用的 CPU 时间越多,可能是性能热点。Y 轴是函数调用栈
2.4 生成红蓝差分火焰图
在某些情况下我们关心的是加上某项功能后,性能的对比情况。这种情况下需要用到差分火焰图来进行分析:
首先我们使用 perf record 抓取一次新的数据:
在对比新旧数据,使用对比结果给 cp.svg 重新上色:
而在红/蓝差分火焰图中, 使用不同的颜色来表示两个文件中的差异部分。红色表示增长, 蓝色表示衰减:
2.5 火焰图优点
互动性:火焰图是基于 stack 信息生成的 SVG 图片, 用来展示 CPU 的调用栈,可以与用户互动。
访达查看:点击某一层,火焰图会水平放大,该层占据所有宽度,显示详细信息。此时左上角会显示”reset zoom“,点击后图片就会恢复当原样。
搜索:按下 Ctrl+f 会显示一个搜索框,用户可以输入关键词过着正则表达式,符合条件的函数会高亮显示。
版权声明: 本文为 InfoQ 作者【芯动大师】的原创文章。
原文链接:【http://xie.infoq.cn/article/cb0a03a6638333a34a1bfa34f】。文章转载请联系作者。
评论