什么是Perf
Perf在wiki中的定义:Linux profiling with performance counters,其实Perf的强大远强于counters这一定义。
Perf是内置于Linux内核源码树中的性能剖析(profiling)工具。它基于事件采样原理,以性能事件为基础,支持针对处理器相关性能指标与操作系统相关性能指标的性能剖析,常用于性能瓶颈的查找与热点代码的定位。
最初的时候,它叫做Performance counter,在2.6.31内核版本中第一次亮相。此后他成为内核开发最为活跃的一个领域。在2.6.32中它正式改名为Performance Event,因为perf已不再仅仅作为 PMU 的抽象,而是能够处理所有的性能相关的事件。
Perf是一个工具集,可以通过perf --help来查看所有的参数和命令,其中最常用的有如下五个:perf-list、perf-stat、perf-top、perf-record、perf-report。下面就详细说明一下这五个命令的使用技巧和背景。
perf-list
Perf-list用来查看perf所支持的性能事件,有软件的也有硬件的。通过 perf list --help可以查看perf list的可用参数。
其中性能事件的包括:Hardware event、Software event、Hardware cache event、tracepoint:Tracepoint event。sw实际上是内核的计数器,与硬件无关。hw和cache是CPU架构相关的,依赖于具体硬件。tracepoint是基于内核的ftrace,是内核中的静态tracepoint所触发的事件,这些tracepoint用来判断程序运行期间内核的行为细节,比如slab分配器的分配次数等。
perf-stat
用于分析指定程序的性能概况。举个例子:执行perf stat php call_test.php得到的结果如下所示:
有一些显示的not supported,可能是因为我是虚拟机,某些检测能力没有开启。不过这并不重要,我来罗列一下所有字段的含义:
task-clock:任务真正占用的处理器时间,单位为ms。
context-switches:上下文的切换次数。
CPU-migrations:处理器迁移次数。Linux为了维持多个处理器的负载均衡,在特定条件下会将某个任务从一个CPU迁移到另一个CPU。
page-faults:缺页异常的次数。当应用程序请求的页面尚未建立、请求的页面不在内存中,或者请求的页面虽然在内存中,但物理地址和虚拟地址的映射关系尚未建立时,都会触发一次缺页异常。
cycles:消耗的处理器周期数。如果把被ls使用的cpu cycles看成是一个处理器的,那么它的主频为2.486GHz。
instructions:执行了多少条指令。IPC为平均每个cpu cycle执行了多少条指令。
branches:遇到的分支指令数。branch-misses是预测错误的分支指令数。
下面介绍几个使用例子:
perf stat -r 10 ls > /dev/null 执行10次程序,给出标准偏差与期望的比值
perf stat -v ls > /dev/null 显示更详细的信息
perf stat -n ls > /dev/null 只显示任务执行时间,不显示性能计数器
perf stat -a -A ls > /dev/null 单独给出每个CPU上的信息
perf stat -e syscalls:sys_enter ls ls命令执行了多少次系统调用
perf top
对于一个指定的性能事件(默认是CPU周期),显示消耗最多的函数或指令。perf top类似linux的top命令,可以排列展示当机的函数和指令消耗情况。perf top主要用于实时分析各个函数在某个性能事件上的热度,能够快速的定位热点函数,包括应用程序函数、模块函数与内核函数,甚至能够定位到热点指令。默认的性能事件为cpu cycles。效果如下:
第一列:符号引发的性能事件的比例,默认指占用的cpu周期比例。
第二列:符号所在的DSO(Dynamic Shared Object),可以是应用程序、内核、动态链接库、模块。
第三列:DSO的类型。[.]表示此符号属于用户态的ELF文件,包括可执行文件与动态链接库)。[k]表述此符号属于内核或模块。
第四列:符号名。有些符号不能解析为函数名,只能用地址表示。
perf top也可以针对一个特定进程进行监控,用-p的参数来标记PID即可。
常用的使用方式有:
perf top //默认配置
perf top -G //得到调用关系图
perf top -e cycles //指定性能事件
perf top -p pid //查看这两个进程的cpu cycles使用情况
perf top -s comm,pid,symbol //显示调用symbol的进程名和进程号
perf top --comms nginx,top //仅显示属于指定进程的符号
perf top --symbols kfree // 仅显示指定的符号
perf-record
收集采样信息,并将其记录在数据文件中。随后可以通过其它工具(perf-report)对数据文件进行分析,结果类似于perf-top的。
基本的使用方法:
perf record xxx //执行命令即可
perf record -p pid //针对特定进程
perf-report
perf report是读取perf record的数据来做分析,并给出热点分析结果。
基本使用方法:perf report -i perf.data
下面结合perf record和perf report我们来做一下实例演示。
执行perf record命令对PHP的一个脚本进行监控,得到一个perf.data数据文件。然后执行perf report -i perf.data就可以得到数据视图。
就视图的展示方式而言,很类似perf top,但对会命令和函数给出耗时的占比,还可以细化到汇编语言查看耗时原因。
perf的火焰图
perf的数据可以进一步被加工为火焰图,这需要其他工具的支持,据我看到不少人介绍到了flameGap这个开源项目(https://github.com/brendangregg/FlameGraph.git),里面有很多的perl脚本。大概是长这个样子。
通过如下命令:
perf record -g ls
perf script -i perf.data &> perf.unfold
./stackcollapse-perf.pl perf.unfold &>perf.folded
./stackcollapse-perf.pl perf.unfold >perf.svg
就可以得到截图中的perf.svg矢量图片了。下载下来打开大概是这个样子: