Perf全名是Performance Event,是在Linux 2.6.31 以后内建的系统效能分析工具,它随着核心一并释出。藉由perf,应用程式可以利用PMU (Performance Monitoring Unit), tracepoint 和核心内部的特殊计数器(counter) 来进行统计,另外还能同时分析运行中的核心程式码,从而更全面了解应用程式中的效能瓶颈。
相较于OProfile和GProf,perf 的优势在于与Linux Kernel 紧密结合,并可受益于最先纳入核心的新特征。perf 基本原理是对目标进行取样,纪录特定的条件下所侦测的事件是否发生以及发生的次数。例如根据tick 中断进行取样,即在tick 中断内触发取样点,在取样点里判断行程(process) 当时的context。假如一个行程90% 的时间都花费在函式foo() 上,那么90% 的取样点都应该落在函式foo() 的上下文中。
Perf 可取样的事件非常多,可以分析Hardware event,如cpu-cycles、instructions 、cache-misses、branch-misses …等等。可以分析Software event,如page-faults、context-switches …等等,另外一种就是Tracepoint event。知道了cpu-cycles、instructions 我们可以了解Instruction per cycle 是多少,进而判断程式码有没有好好利用CPU,cache-misses 可以晓得是否有善用Locality of reference ,branch-misses 多了是否导致严重的pipeline hazard ?另外Perf 还可以对函式进行采样,了解效能卡在哪边。
安装
首先利用以下指令查看目前的Kernel config 有没有启用Perf。如果PC 上是装一般Linux distro,预设值应该都有开启。
$ cat "/boot/config-`uname -r`" | grep "PERF_EVENT"
前面讲到,perf 是Linux 内建支持的效能优化工具,在2.6.31 版本之后,我们可以直接到Linux Kernel Archives下载对应版本的程式码,解压缩后到tools/perf里面去编译,通常过程中会有相依的套件需要安装,依指示完成安装后,编译即可成功,最后再把编译完成的perf 移至 中/usr/bin就可以使用了。这种方法通常适用于更新过kernel 的使用者,因为更新过kernel 后会造成distribution package 与kernel version 不相符。一般使用者采用第二种方法即可。
使用apt-get 进行安装。
$ sudo apt-get install linux-tools-common
接着输入perf list 或perf top 检查一下perf 可不可以使用。
如果出现以下的信息,表示还漏了些东西。
WARNING: perf not found for kernel 3.16.0-50
You may need to install the following packages for this specific kernel:
linux-tools-3.16.0-50-generic
linux-cloud-tools-3.16.0-50-generic
上面的Kernel 版本可能和你不一样,根据指示安装起来即可。不放心的话可以使用$ uname -r确认。
$ sudo apt-get install linux-tools-3.16.0-50-generic linux-cloud-tools-3.16.0-50-generic
到这里perf 的安装就完成了。不过这里我再稍微补充一下,如果你不是切换到root 的情况下输入
$ perf top
kernel.perf_event_paranoid 是用来决定你在没有root 权限下(Normal User) 使用perf 时,你可以取得哪些event data。预设值是1 ,你可以输入
$ cat /proc/sys/kernel/perf_event_paranoid
来查看权限值。一共有四种权限值:
2: 不允许任何量测。但部份用来查看或分析已存在的纪录的指令仍可使用,如perf ls、perf report、perf timechart、 perf trace。
1: 不允许CPU events data。但可以使用perf stat、perf record 并取得Kernel profiling data。
0: 不允许raw tracepoint access。但可以使用perf stat、perf record 并取得CPU events data。
-1: 权限全开。
最后如果要检测cache miss event ,需要先取消kernel pointer 的禁用。
$ sudo sh -c " echo 0 > /proc/sys/kernel/kptr_restrict"
perf top -p $pid
Perf 能触发的事件分为三类:
hardware : 由PMU 产生的事件,比如cache-misses、cpu-cycles、instructions、branch-misses …等等,通常是当需要了解程序对硬体特性的使用情况时会使用。
software : 是核心程式产生的事件,比如context-switches、page-faults、cpu-clock、cpu-migrations …等等。
tracepoint : 是核心中的静态tracepoint 所触发的事件,这些tracepoint 用来判断在程式执行时期,核心的行为细节,比如slab 记忆体配置器的配置次数等。
Perf 包含20 几种子工具集
perf top 其实跟平常Linux 内建的top 指令很相似。它能够「即时」的分析各个函式在某个event 上的热点,找出拖慢系统的凶手,就如同上面那个范例一样。甚至,即使没有特定的程序要观察,你也可以直接下达$ perf top指令来观察是什么程序吃掉系统效能,导致系统异常变慢。
可以发现红色热点就出现了。右边第一列为各函式的符号,左边第一行是该符号引发的event 在整个「监视域」中占的比例,我们称作该符号的热度,监视域指的是perf 监控的所有符号,预设值包括系统所有程序、核心以及核心module 的函式,左边第二行则为该符号所在的Shared Object 。若符号旁显示[.]表示其位于User mode,[k]则为kernel mode。
perf stat
相较于top,使用perf stat 往往是你已经有个要优化的目标,对这个目标进行特定或一系列的event 检查,进而了解该程序的效能概况。(event 没有指定的话,预设会有十种常用event。)
$ perf stat --repeat 5 -e cache-misses,cache-references,instructions,cycles ./perf_stat_cache_miss
--repeat <n>或是-r <n>可以重复执行n 次该程序,并显示每个event 的变化区间。cache-misses,cache-references和instructions,cycles类似这种成对的event,若同时出现perf 会很贴心帮你计算比例。
根据这次perf stat 结果可以明显发现程序有很高的cache miss,连带影响IPC 只有0.65。
perf record & perf report 有别于stat,record 可以针对函式级别进行event 统计,方便我们对程序「热点」作更精细的分析和优化。我们来对以下程式,使用perf record 进行branch 情况分析
$ perf record -e branch-misses:u,branch-instructions:u ./perf_record_example
$ perf report
:u是让perf 只统计发生在user space 的event。最后可以观察到回圈展开前后branch-instructions 的差距。
另外,使用record 有可能会碰到的问题是取样频率太低,有些函式的讯息没有没显示出来(没取样到),这时可以使用来调高取样频率,可以输入以下查看最大值,要-F <frequcncy>更改也没问题,但能调到多大可能还要查一下。
$ cat /proc/sys/kernel/perf_event_max_sample_rate