perf报告中mem_access与缓存访问总和数值差距的技术疑问
ARMv8下perf
mem_access与缓存事件总和差距的原因分析 核心原因:统计范围与口径的差异
你观察到的mem_access数值远大于缓存加载类事件总和,本质是两者的统计范围完全不对等,具体拆解如下:
1. mem_access包含存储(Store)操作,而你未统计任何存储类缓存事件
在ARMv8架构的PMU(性能监控单元)中,mem_access事件统计的是CPU核心发起的所有内存访问操作,包括:
- 所有执行(含推测执行后取消)的数据加载(Load)指令
- 所有执行(含推测执行后取消)的数据存储(Store)指令
而你采集的缓存指标(L1-dcache-loads、L1-icache-loads、LLC-loads)均为加载类事件,完全未覆盖存储类的缓存访问(比如L1-dcache-stores、LLC-stores)。程序中必然存在大量数据存储操作,这是两者差距的最主要来源。
2. 统计维度的本质区别
mem_access的统计对象是内存访问指令的执行次数:每一条Load/Store指令(即使是推测执行后被取消的)都会被计数1次。- 缓存类事件(如
L1-dcache-loads)的统计对象是缓存层级的请求次数:包括CPU主动发起的指令/数据请求,以及硬件预取器发起的缓存请求。两者的统计维度不同,部分场景下会出现计数差异:- 硬件预取的缓存请求会被
L1-dcache-loads统计,但不会被mem_access计数(因为预取是硬件主动发起,不是执行指令触发); - 推测执行后被取消的Load/Store指令会被
mem_access统计,但不会触发完整的缓存请求,因此不会被缓存类事件计数。
- 硬件预取的缓存请求会被
验证方法
要缩小两者的差距,你可以补充采集存储类缓存事件后再对比:
- 调整perf命令,加入
L1-dcache-stores、LLC-stores等存储类指标:sudo perf stat -e cpu-cycles,cache-misses,instructions,inst_spec,stalled-cycles-frontend,stalled-cycles-backend,L1-dcache-load-misses,L1-icache-load-misses,LLC-loads,LLC-load-misses,context-switches,branch-load-misses,branch-loads,mem_access,L1-dcache-loads,L1-icache-loads,L1-dcache-stores,LLC-stores ./no_false_sharing - 用
perf list mem_access查看该事件对应的具体PMU编码与官方定义,确认其统计范围。
关于伪共享场景的补充
当启用BadWorker触发伪共享时,多个核心频繁修改同一缓存行内的不同变量,会导致大量缓存行失效与重新加载:
- 此时
LLC-load-misses、cache-misses等指标会大幅上升; mem_access的计数也会显著增加,因为每个核心的Store操作会触发其他核心的缓存失效,进而引发更多的Load操作来重新加载缓存行。
内容的提问来源于stack exchange,提问作者kaixin liu
相关产品推荐
相关产品推荐

