perf_event_open系统调用同时开启系统/进程模式事件是否有数量限制
问题结论
你遇到的进程模式下PMU计数为0的问题和perf_event_open支持的最大事件数量无关,是硬件PMU资源抢占+内核perf事件调度优先级导致的问题。
核心原因
- 主流架构(如x86、ARM)的CPU每个核心仅配备3~8个通用可编程物理PMU计数器,硬件层面可同时运行的PMU事件上限很低,当开启的事件数超过物理计数器数量时,内核会通过时间分片的方式调度不同事件轮流占用计数器。
- 系统模式(PID=-1)的PMU事件调度优先级默认高于进程模式的事件:如果系统模式事件已经占满了所有可用的物理PMU计数器,进程模式事件将始终无法获得计数器时间片,因此读取到的计数恒为0。
- 你用
perf stat复现的结果也符合该逻辑:不带进程参数的perf stat默认运行在系统模式,优先级更高,占满计数器后指定PID的进程模式事件就无法拿到计数资源。
验证方法
你可以通过以下操作确认该判断:
- 先减少同时开启的系统模式PMU事件数量,预留出至少1个空闲物理计数器后再开启进程模式事件,观察进程模式计数是否恢复正常。
- 给进程模式事件的
perf_event_attr结构体设置pinned = 1,强制内核优先调度该进程模式事件,此时会出现系统模式事件计数为0的反向表现,符合优先级抢占规则。 - 读取
perf_event_open返回的计数拓展字段,确认time_running值:如果进程模式事件的time_running恒为0,说明该事件始终没有被调度到物理计数器上。
解决方案
如果需要同时采集系统级和进程级PMU事件,可以参考以下方案规避该问题:
- 减少同时开启的硬件PMU事件数量,优先使用不需要占用物理PMU计数器的软件事件、Tracepoint事件。
- 对事件进行分组配置,通过
perf_event_attr的group_fd参数把关联事件放在同一组,减少计数器资源占用。 - 开启perf事件时间复用机制,根据
time_enabled和time_running的比值对计数结果做估算修正。
内容的提问来源于stack exchange,提问作者Hccccc
相关产品推荐
相关产品推荐

