Perf API引发大量内核LLC读访问?求排查与过滤方案
问题解答
1. 是否确实由Perf API引发该问题?
是的,大概率是Perf自身的内核开销导致的。
你观察到无论用户态循环逻辑如何修改,内核级LLC读计数基本不变,这符合Perf事件框架的特性:当你调用perf_start_measurement_group和perf_stop_measurement_group时,内核的Perf子系统需要完成一系列操作——比如初始化事件计数器、同步事件组状态、读取计数结果等,这些操作都会产生内核级的LLC访问,且这部分开销是固定的,和用户态的测试逻辑无关。尤其是你使用了事件组,内核需要协调多个计数器的启停和数据读取,这会进一步带来固定的缓存访问开销,正好对应你看到的约80000次计数。
2. 若要忽略Perf自身引入的内核事件,但保留对其他内核事件的监控,该如何操作?
有两种实用的方案:
方案一:基准差值法(最简单易实现)
先单独测量Perf启停操作本身带来的内核开销,再从实际测试结果中减去这个基准值:
- 编写空测试代码:只调用
perf_start_measurement_group和perf_stop_measurement_group,不运行任何用户态测试循环。 - 多次运行空测试(比如10次),取内核LLC读计数的平均值,得到Perf自身的固定开销基数。
- 运行真实测试时,用得到的总内核计数减去这个基数,就是排除Perf自身开销后的真实内核事件计数。
方案二:内核事件过滤法(更精准,需内核支持)
利用Perf的事件过滤机制,过滤掉Perf子系统自身产生的事件:
- 在初始化
perf_event_attr结构体时,设置filter字段,过滤掉Perf相关内核线程或函数的事件。例如,过滤掉comm名称为perf的内核线程产生的事件:attr.filter = "comm != \"perf\""; - 如果你需要更精准的过滤,可以针对Perf子系统的核心函数(如
perf_event_read、perf_event_stop等)进行过滤,不过这需要熟悉内核Perf子系统的函数名,且内核需支持基于kprobe或函数的事件过滤(通常5.0以上内核支持)。
注意:方案二需要确保你的内核版本支持Perf事件过滤功能,且过滤规则要准确,避免误过滤其他合法的内核事件。
内容的提问来源于stack exchange,提问作者ddaa
相关产品推荐
相关产品推荐

