Author:Onceday Date:2023年9月3日
漫漫长路,才刚刚开始…
参考文档:
perf list
用于列出可用的性能事件,这些事件可以用于 perf record
和其他 perf
子命令的性能分析。性能事件包括硬件事件(如 CPU 周期、缓存未命中等)、软件事件(如上下文切换、页面错误等)和跟踪点事件(如内核函数调用、用户空间应用程序的跟踪等)。
Usage: perf list [] [hw|sw|cache|tracepoint|pmu|sdt|metric|metricgroup|event_glob]
-d, --desc Print extra event descriptions. --no-desc to not print.
-j, --json JSON encode events and metrics
-v, --long-desc Print longer event descriptions.
--debug Enable debugging output
--deprecated Print deprecated events.
--details Print information on the perf event names and expressions used internally by events.
--unit
Limit PMU or metric printing to the specified PMU.
上面是在linux kernel6.2版本的perf list帮助输出,perf工具和linux内核以及硬件高度绑定,因此不同的内核版本,虚拟机,硬件环境下,perf list的输出会有较大差别。许多性能事件是否可用,需要取决于当前硬件和软件环境。
perf工具支持一系列可测量的事件。该工具和底层内核接口可以测量来自不同来源的事件。例如,有些事件是纯内核计数器,在这种情况下称为软件事件。例如:上下文切换、小故障。
事件的另一个来源是处理器本身及其性能监控单元(PMU)。它提供了一个事件列表来测量微体系结构事件,如周期数、指令退役、L1缓存缺失等。这些事件被称为PMU硬件事件或简称硬件事件。它们因处理器类型和型号而异。
perf_events接口还提供了一组常用的硬件事件名称。在每个处理器上,如果这些事件存在,则将它们映射到CPU提供的实际事件上,否则无法使用事件。有些令人困惑的是,这些事件也称为硬件事件(hardware event)和硬件缓存事件(hardware cache event)。
最后,还有由内核ftrace基础设施实现的tracepoint事件。这些仅在2.6.3 3x和更新的内核中可用。
PMU硬件事件是特定于CPU的,并由CPU供应商记录。如果链接到libpfm4, perf工具库会提供一些事件的简短描述。有关Intel和AMD处理器的PMU硬件事件列表,请参见:
perf list列出来的这些事件就是本机设备上受支持性能事件,后面中括号里面就是具体的事件类型,这些事件可能会非常多,不同的账户权限执行的结果也会有些不同。
对于非root用户,通常只有上下文切换的PMU事件可用。这通常只是cpu PMU中的事件、预定义的事件(如周期和指令)以及一些软件事件。其他pmu和全局测量通常仅为root
可用。一些事件限定符,如“any”,也是root
限定符。这可以通过设置kernel.perf_event_paranoid
为-1
来修改(使用sysctl),允许非root用户使用这些事件。为了访问跟踪点事件,perf
需要对/sys/kernel/debug/tracing具有读访问权限,即使perf_event_paranoid
处于宽松设置中也是如此。
--unit
选项在使用 perf list
时用于将事件或指标的输出限制为特定的性能监视单元(Performance Monitoring Unit,PMU)。PMU 是处理器的一个组件,它可以计数硬件事件,如执行的指令、遭受的缓存未命中或错误预测的分支。它们为应用程序分析提供了基础,可以追踪动态控制流并识别热点。
以下是如何使用它的示例:
perf list --unit cpu
此命令将列出 CPU PMU 可用的所有事件或指标。PMU 名称需要事先知道,具体取决于硬件和内核的支持。一些常见的 PMU 名称包括 cpu
、cache
、bus
和 software
。
请记住,根据您的硬件和内核配置,可能并非所有 PMU 都可用。
--details
会额外打印符号事件(cycles, cache-misses等)的内部表达形式,如下:
cache-misses OR cpu/cache-misses/ [Kernel PMU event]
cpu/event=0x64,umask=0x9/
cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event]
cpu/event=0x76/
事件是用它们的符号名和可选的单位掩码和修饰符来指定的。事件名称(Event names)、单元掩码(unit masks)和修饰符(modifiers)不区分大小写。一般的情况下,可以使用cache-misses
这种符号形式来代替cpu/event=0x64,umask=0x9/
这种格式。
默认情况下,事件是在用户和内核级别度量的:
perf stat -e cycles dd if=/dev/zero of=/dev/null count=100000
若要仅在用户级别进行度量,则需要传递一个修饰符(u):
perf stat -e cycles:u dd if=/dev/zero of=/dev/null count=100000
要测量用户和内核(显式地):
perf stat -e cycles:uk dd if=/dev/zero of=/dev/null count=100000
事件可以通过附加冒号和一个或多个修饰符来选择具有修饰符。修饰符允许用户限制何时对事件进行计数。修饰符如下:
名称标识 | 描述 |
---|---|
u | user-space counting,用户空间 |
k | kernel counting,内核空间 |
h | hypervisor counting,虚拟机 |
I | non idle counting,非空闲时 |
G | guest counting (in KVM guests),KVM虚拟机 |
H | host counting (not in KVM guests),KVM主机 |
p | precise level,硬件事件精度级别 |
P | use maximum detected precise level,使用最大检测精度水平 |
S | read sample value (PERF_SAMPLE_READ)读取样本值 |
D | pin the event to the PMU,将事件绑定到PMU上 |
W | 组是弱的,如果不可调度,将退回到非组 |
e | 群组或事件是排他性的,不共享PMU |
p修饰符可用于指定指令地址的精确程度。p修饰符可以被指定多次:
对于英特尔系统,精确事件采样是用PEBS实现的,它支持精确级别2,在某些特殊情况下支持精确级别3。
在AMD系统上,它是使用IBS实现的(最高精确级别到2)。精确修饰符与事件类型0x76 (cpu-cycles,CPU时钟未停止)和0xC1(micro-ops retired)一起工作。
默认情况下,perf list列出所有的已知事件。也可以通过下面的类别来列出其中某一类事件:
事件类名称 | 描述 |
---|---|
hw or hardware | 列出硬件事件,如cache-misses |
sw or software | 列出软件事件,例如上下文切换(context switches) |
cache or hwcache | 列出硬件缓存事件,如L1-dcache-loads |
tracepoint | 列出所有的tracepoint事件,也可使用subsys_glob:event_glob去过滤子系统追踪点事件,如sched、block等。 |
pmu | 打印内核提供的PMU事件 |
sdt | 列出所有静态定义的跟踪点事件(Statically Defined Tracepoint) |
metric | 指标列表(度量事件) |
metricgroup | 列出带有指标的指标组 |
–raw-dump | 显示所有事件的原始格式信息,该选项后面可以接[hw|sw|cache|tracepoint|pmu|event_glob] |
本章详细内容可以参考文档: perf-list(1) - Linux manual page (man7.org)
即使现在在perf中没有符号形式的事件,也可以用特定于每个处理器的方式对其进行编码。
比如对于X86CPUs,要测量CPU硬件供应商文档中提供的实际PMU,可以传递十六进制参数代码:
perf stat -e r1a8 -a sleep 1
perf record -e r1a8 ...
有些处理器,比如AMD的处理器,支持大于一个字节的事件代码和单元掩码。在这种情况下,与事件配置参数对应的位可以参考下面命令的结果:
cat /sys/bus/event_source/devices/cpu/format/event
比如可能的命令如下:
perf record -e r20000038f -a sleep 1
perf record -e cpu/r20000038f/ ...
perf record -e cpu/r0x20000038f/ ...
有关于特定硬件上的PMU事件,需要参考处理器的说明文档来确定使用方法。
在下面的路径可以查看可用的PMUs和它们的原始参数:
ls /sys/devices/*/format
一些pmu不与核心相关联,而是与整个CPU socket
相关联。这些pmu上的事件通常不能采样,只能使用perf stat -a
进行全局计数。它们可以绑定到一个逻辑CPU,但是会测量同一个插槽中的所有CPU。
本例在Intel Xeon系统的socket 0
上的第一个内存控制器上每秒测量内存带宽:
perf stat -C 0 -a uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/ -I 1000 ...
每个内存控制器都有自己的PMU。测量整个系统带宽需要指定所有imc pmu(请参阅perf list output),并将这些值相加。为了简化多个事件的创建,在PMU名称中支持前缀和全局匹配,并且在执行匹配时也忽略前缀uncore_。因此,上面的命令可以通过使用以下语法扩展到所有内存控制器:
perf stat -C 0 -a imc/cas_count_read/,imc/cas_count_write/ -I 1000 ...
perf stat -C 0 -a *imc*/cas_count_read/,*imc*/cas_count_write/ -I 1000 ...
有一些pmu事件列出来的时候,其显示字符中带有?
号。如下:
hv_gpci/dtbp_ptitc,phys_processor_idx=?/
这意味着当作为事件提供时,?
所指示的内容必须也可提供。
perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ...
此外还有可能指定额外的事件修饰符(percore):
perf stat -e cpu/event=0,umask=0x3,percore=1/
上面命令即汇总一个核心中所有硬件线程的事件计数。
当活动事件的数量超过硬件性能计数器的数量时,Perf支持基于时间的事件复用。当工作负载更改其执行配置文件时,多路复用可能导致测量错误。
当使用来自事件计数的公式计算度量时,确保始终将一些事件作为一个组一起测量以最小化多路错误是很有用的。事件组可以使用{}
指定。
perf stat -e '{instructions,cycles}' ...
可用性能计数器的数量取决于CPU。一个组不能包含比可用计数器更多的事件。例如,Intel Core cpu通常有四个通用的核心性能计数器,加上三个固定的instructions
、cycles
和ref-cycles
计数器。一些特殊事件对它们可以调度的计数器有限制,并且可能不支持单个组中的多个实例。当组中指定的事件太多时,其中一些事件将无法测量。
全局固定事件可以限制其他组可用的计数器数量。在x86系统上,NMI看门狗默认固定一个计数器。NMI看门狗可以在root用户下禁用:
echo 0 > /proc/sys/kernel/nmi_watchdog
来自多个不同pmu的事件不能混合在一个组中,软件事件除外。
perf还支持使用:S
说明符进行组领导抽样(group leader sampling
)。
perf record -e '{cycles,instructions}:S' ...
perf report --group
通常情况下,所有事件都在一个事件组样本中,但是使用:S
时,只有第一个事件(leader)进行采样,它只读取组中其他事件的值。然而,在AUX区域事件(例如Intel PT或CoreSight)的情况下,AUX区域事件必须是先导事件,因此第二个事件采样,而不是第一个事件。