介绍
perf 是 Linux 2.6.31 以后内置的性能分析工具。它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。
使用介绍
perf top
类似于 top,它能够实时显示占用 CPU 时钟最多的函数或者指令,因此可以用来查找热点函数
$ perf top Samples: 833 of event 'cpu-clock', Event count (approx.): 97742399 Overhead Shared Object Symbol 7.28% perf [.] 0x00000000001f78a4 4.72% [kernel] [k] vsnprintf 4.32% [kernel] [k] module_get_kallsym 3.65% [kernel] [k] _raw_spin_unlock_irqrestore ...
解析:输出结果中,第一行包含三个数据,分别是采样数(Samples)、事件类型(event)和事件总数量(Event count)。比如这个例子中,perf 总共采集了 833 个 CPU 时钟事件,而总事件数则为 97742399。
再往下看是一个表格式样的数据,每一行包含四列,分别是:
第一列 Overhead ,是该符号的性能事件在所有采样中的比例,用百分比来表示。
第二列 Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
第三列 Object ,是动态共享对象的类型。比如 [.] 表示用户空间的可执行程序、或者动态链接库,而 [k] 则表示内核空间。
最后一列 Symbol 是符号名,也就是函数名。当函数名未知时,用十六进制的地址来表示。
Self 是最后一列的符号(可以理解为函数)本身所占比例;
Children 是这个符号调用的其他符号(可以理解为子函数,包括直接和间接调用)占用的比例之和。
perf record 和 perf report
perf top 虽然实时展示了系统的性能信息,但它的缺点是并不保存数据,也就无法用于离线或者后续的分析。而 perf record 则提供了保存数据的功能,保存后的数据,需要你用 perf report 解析展示
$ perf record # 按Ctrl+C终止采样 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.452 MB perf.data (6093 samples) ] $ perf report # 展示类似于perf top的报告
注意:实际使用中perf top 和 perf record 加上 -g 参数,开启调用关系的采样,方便我们根据调用链来分析性能问题。
查看指定进程
# -g开启调用关系分析,-p指定php-fpm的进程号21515 $ perf top -g -p 21566
注意事项
1、有的时候perf 看到的是16进制地址而不是函数名字
原因:很可能是perf 找不到待分析进程依赖的库,尤其是分析的进程是docker 启动的,进程依赖的库也在docker里面,然后perf是在宿主机上面运行的,所以找不到依赖的库
解决:在容器外面把分析纪录保存下来,再去容器里查看结果。这样,库和符号的路径也就都对了。比如,你可以这么做。先运行 perf record -g -p < pid>,执行一会儿(比如 15 秒)后,按 Ctrl+C 停止。然后,把生成的 perf.data 文件,拷贝到容器里面来分析
2、perf 的报告中,很多符号都不显示调用栈
原因:通过man 查询得知 per 报告中 threshold 的默认值为 0.5%,也就是说,事件比例超过 0.5% 时,调用栈才能被显示。
解决: perf report -g graph,0.3 #自己设定最低值,如果你的服务进程在0.32左右那么可以设置一个低于0.32的值。
3、性能损耗
perf 它需要在内核中跟踪内核栈的各种事件,那么不可避免就会带来一定的性能损失。这一点,虽然对大部分应用来说,没有太大影响,但对特定的某些应用(比如那些对时钟周期特别敏感的应用),可能就是灾难了。所以,使用性能工具时,确实应该考虑工具本身对系统性能的影响。而这种情况,就需要你了解这些工具的原理。
比如,perf 这种动态追踪工具,会给系统带来一定的性能损失。
vmstat、pidstat 这些直接读取 proc 文件系统来获取指标的工具,不会带来性能损失。