Linux 性能计数器,用于为内核子系统分析提供一个框架。它支持硬件级别(CPU/PMU,性能监控单元)特性和软件特性(软件计数器,tracepoints)。
perf是跟 Linux 内核版本相关的,其源代码在 kernel 源码的 tools/perf 文件夹下。
make perf
命令就可编译出对应内核的 perf 工具;make tools/perf
命令同样可以编译出对应内核的 perf 工具;perf [–version] [–help] [OPTIONS] COMMAND [ARGS]
-h 打印帮助内容
-v 显示 perf 的版本
-vv 显示库已编译的状态
–exec-path 显示或者设置执行的路径
–html-path 显示 html 文档的路径
-p 设置
–no-pager
–buildid-dir 安装buildid缓存目录。它的优先级高于buildid.dir配置文件选项
–list-cmds 列出使用的 perf 命令
–list-opts 显示有效的 perf 选项
–debugfs-dir 设置 debugfs 目录或者设置 PERF_DEBUGFS_DIR 环境变量
–debug 设置调试变量的范围(0,10)
例如:–debug verbose = 2
事件可以选择通过附加冒号和一个或多个修饰符来具有修饰符。 修饰符允许用户限制要计数的事件。
u - 用户空间计数
k - 内核空间计数
h - 管理程序计数
I - 非空闲状态计数
G - 客户端计数 (在 KVM 客户端使用)
H - 主机端计数 (不在 KVM 客户端)
p - 使用精确级别
P - 使用最大检测到的精确级别
S - 读取样本值 (PERF_SAMPLE_READ)
D - 将事件固定到 PMU
W - group is weak and will fallback to non-group if not schedulable,
e - 组或活动是排他性的,不共享 PMU
‘p’ 修饰符可用于指定指令地址的精确度。 ‘p’ 修饰符可以指定多次:
0 - SAMPLE_IP 可以有任意的打断
1 - SAMPLE_IP 必须具有恒定的中断
2 - SAMPLE_IP 不允许被中断
3 - SAMPLE_IP 不允许被中断,或使用随机化以避免样本阴影效应。
Tips
- intel CPU
对于 Intel 系统,精确事件采样是通过 PEBS 实现的,PEBS 最高支持精确级别 2,在某些特殊情况下还支持精确级别 3- amd CPU
在 AMD 系统上,它是使用 IBS 实现的(最高精确级别 2)。Precision 修饰符适用于事件类型 0x76(CPU 周期、CPU 时钟未停止)和 0xC1(微操作已停用)。 两个事件都映射到 IBS 执行采样 (IBS op),并分别设置 IBS Op 计数器控制位 (IbsOpCntCtl)(请参阅 [AMD 处理器的 Core Complex (CCX) -> 处理器 x86 Core -> 基于指令的采样 (IBS) 部分) 编程参考 (PPR)] 与所使用的处理器的系列、型号和步进相关)。
perf record -a -e cpu-cycles:p … # use ibs op counting cycles
perf record -a -e r076:p … # same as -e cpu-cycles:p
perf record -a -e r0C1:p … # use ibs op counting micro-ops
即使事件目前在 perf 中无法以符号形式提供,它也可以以每个处理器特定的方式进行编码。
例如:
intel 的 QM720 酷睿 i7 的一个事件如下:
Event Num. | Umask Value | Event Mask Mnemonic | Description | Comment |
---|---|---|---|---|
A8H | 01H | LSD.UOPS | Counts the number of micro-ops delivered by loop stream detector | Use cmask=1 and invert to count cycles |
原始编码 0x1A8 可以被如下方法使用:
perf stat -e r1a8 -a sleep 1
perf record -e r1a8 ...
pmu 的语法结构为:
perf record -e r1a8 -a sleep 1
perf record -e cpu/r1a8/ ...
perf record -e cpu/r0x1a8/ ...
一些处理器支持事件代码和单位掩码
例如 :
amd 的 EPYC 7713处理器的一个事件如下:
Event Num. | Umask Value | Event Mask Mnemonic | Description |
---|---|---|---|
28FH | 03H | op_cache_hit_miss.op_cache_hit | Counts Op Cache micro-tag hit events. |
无法使用 0x0328F 的原始编码,因为 EventSelect 位的高半字节必须通过位 32-35 指定,如下所示:
cat /sys/bus/event_source/devices/cpu/format/event
使用 0x20000038F
perf stat -e r20000038f -a sleep 1
perf record -e r20000038f ...
这些参数需要从处理器的规格书中进行查找。
有效的 PMUs 和对应的原始参数可以从以下目录中查找:
ls /sys/devices/*/format
此处的 “SOCKET” 是指 CPU 的插座,即一个插槽中所包含 CPU 的所有部件 —— 这里需要大家了解 CPU 的 socket 、package 等概念。
一些 PMUs 不是跟 CPU 的一个处理核心相关,而是跟整个 CPU socket 相关。通常这些事件不会被采样,只能使用 perf stat -a 进行全局计数。它们可以绑定到一个逻辑 CPU,但会测量同一插槽中的所有 CPU。
以下示例会在 socket 0 上对 intel 的 Xeon 处理器的第一个内存控制器上进行每秒一次的内存带宽的测量
perf stat -C 0 -a uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/ -I 1000 ...
对于非 root 用户,通常只有上下文切换 PMU 事件可用。
这通常只是 cpu PMU 中的事件、预定义事件(例如周期和指令)以及一些软件事件。
其他 PMU 和全局测量通常需要仅限于 root 权限。
某些事件限定符(例如“any”)也仅限于 root 权限。
我们可以通过将 kernel.perf_event_paranoid sysctl(参考上一章 《Perf 事件和工具安全》) 设置为 -1 来覆盖,这允许非 root 用户使用这些事件。
为了访问跟踪点事件,即使 perf_event_paranoid 处于宽松的设置中,perf 也需要具有对 /sys/kernel/debug/tracing 的读取访问权限。
一些 PMU 控制高级硬件跟踪功能,例如 Intel PT,它允许低开销执行跟踪 —— 这些在单独的 intel-pt.txt 文档中进行了描述。
perf 支持参数化事件,这使得用户可以自定义事件来满足特定的性能分析需求。
perf参数化事件使用的是-f选项,它允许用户定义一个格式化字符串,用于生成自定义的事件名称。格式化字符串中可以包含一个或多个参数,它们将会被替换成具体的值,从而生成事件名称。
例如,下面的命令使用-f选项定义了一个参数化事件:
$ perf record -e '{cpu/event=0x80,umask=0x01,name=custom_event_%d}' -a sleep 5
在这个命令中,我们使用了-f选项来定义了一个参数化事件,其中包含了一个参数%d。这个参数将会被perf工具替换成一个整数,用于生成事件名称。
具体地,这个参数化事件的名称是custom_event_0、custom_event_1、custom_event_2等等,它们的含义是“发生在CPU上,事件代码是0x80,事件计数器的掩码是0x01”的自定义事件。这个事件将会被记录在整个系统的所有进程中,持续5秒钟。
需要注意的是,使用参数化事件需要谨慎,因为如果参数的值过多,将会导致事件数量过多,可能会占用过多的系统资源。因此,应该根据具体情况谨慎使用参数化事件。
可以给事件添加额外限定,例如:指定 percore
示例:
统计在一个核上的所有硬件线程的的事件和
perf stat -e cpu/event=0,umask=0x3,percore=1/
当活动事件的数量超过硬件性能计数器的数量时,Perf 支持基于时间的事件复用。 当工作负载更改其执行配置文件时,多路复用可能会导致测量错误。
当使用事件计数公式计算指标时,确保某些事件始终作为一个组一起测量以最大限度地减少复用错误非常有用。 可以使用 { } 指定事件组。
perf stat -e '{instructions,cycles}' ...
可用性能计数器的数量取决于 CPU。 组包含的事件不能多于可用计数器。当组中指定的事件太多时,其中一些事件将不会被测量。
全局固定事件可以限制其他组可用的计数器数量。 在 x86 系统上,NMI 看门狗默认固定一个计数器。可以使用 root 身份禁用 nmi 看门狗:
echo 0 > /proc/sys/kernel/nmi_watchdog
来自多个不同 PMU 的事件不能混合在一个组中,软件事件除外。
perf 还支持使用 :S 说明符进行组 leader 采样,即仅对第一个事件进行采样:
perf record -e '{cycles,instructions}:S' ...
perf report --group
通常,事件组中的所有事件都会采样,但使用 :S 仅对第一个事件(领导者)进行采样,并且仅读取组中其他事件的值。但是,在 AUX 区域事件(例如 Intel PT 或 CoreSight)的情况下,AUX 区域事件必须是领导者,因此第二个事件采样,而不是第一个事件。
后面将逐步详细介绍每个命令的用法
使用 perf --list-cmds
就可以列出当前 perf 支持的命令。
Linux 源码的说明文档 tools/perf/Documentation