linux perf不直接提供l2/l3缓存命中事件,仅支持未命中(miss)和访问(access/loads)计数器,命中率需通过“访问总数−未命中数”反推,且必须使用语义匹配的硬件事件对(如llc_refs与llc_misses),不同cpu架构(intel/amd/arm)支持事件差异大,虚拟机或权限限制常导致事件不可用。

你不能直接“检测 L2/L3 缓存命中率”——Linux perf 不提供 L2/L3 的 L2-cache-hits 或 L3-cache-hits 这类事件。它只提供未命中(miss)和访问(access/loads)两类基础计数器,且 L2/L3 的可用性严重依赖 CPU 型号与内核支持。
perf 支持哪些 L2/L3 相关事件?
执行 perf list cache 可列出当前系统支持的缓存事件,但结果差异极大:
- Intel 大多数桌面/服务器 CPU(如 Skylake 及以后)支持
L2_RQSTS:ALL_DEMAND_MISS、LLC_MISSES、LLC_REFS等原生 PMU 事件(注意:不是所有都叫L2-*或L3-*,LLC = Last Level Cache,通常指 L3) - AMD Zen2+ 支持
l2_requests、l2_misses(需确认内核版本 ≥ 5.10 且启用CONFIG_AMD_NB) - ARM 平台(如 Neoverse N2)需启用 ARMv8.5-PMU 扩展,否则
l2d_cache_refill等事件不可用 - 虚拟机环境(KVM/QEMU 默认配置)通常禁用 PMU passthrough,
perf list cache可能为空或仅返回软件事件
如何计算 L2/L3 命中率?
没有 hits 事件,只能靠「访问总数 − 未命中数」反推命中数。但关键在于:必须使用语义匹配的一对事件,且它们在硬件上属于同一统计域。
- 对 L3(LLC):推荐组合
LLC_REFS(所有 LLC 引用) +LLC_MISSES→ 命中率 =1 - LLC_MISSES / LLC_REFS - 对 L2:Intel 上常用
L2_RQSTS:ALL_DEMAND_REFERENCES+L2_RQSTS:ALL_DEMAND_MISS;AMD 上用l2_requests+l2_misses - 绝对不要混用:比如用
cache-references(软件抽象事件)配LLC_MISSES(硬件事件),二者统计口径不一致,结果无意义 - 运行命令示例(Intel):
perf stat -e "LLC_REFS,LLC_MISSES" -r 3 ./your_program
为什么你的 perf 输出里看不到 L2/L3 事件?
常见原因不是权限或命令写错,而是底层硬限制:
-
/proc/sys/kernel/perf_event_paranoid值 ≥ 2:会禁用大多数硬件 PMU 事件(包括 LLC 相关),临时修复:echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid - CPU 不支持该事件:例如老款 Intel Haswell 不支持
LLC_REFS,只能退到unhalted-core-cycles+LLC_MISSES做归一化估算 - 内核未编译对应 PMU 驱动:比如 AMD CPU 上缺失
amd_nb模块,lsmod | grep amd可验证 - 你在容器里跑 perf:默认 cgroup v1/v2 会限制 perf event 访问,需加
--privileged或显式挂载perf_eventcgroup
真正能落地的建议
别执着于“精确的 L2/L3 命中率”,它本身意义有限——L3 命中率高不代表程序快(可能只是数据全在 LLC 里反复刷),而 L2 命中率低也不一定差(如果 L3 跟得上)。更实用的做法是:
- 盯住
LLC_MISSES绝对值:下降 30% 通常比命中率从 92%→94% 更有性能价值 - 结合
mem-loads和mem-stores看内存带宽压力,避免把缓存问题误判为内存瓶颈 - 用
perf record -e LLC_MISSES -g定位哪段函数触发最多 L3 miss,再看其访存 pattern 是否连续、是否对齐、是否跨 cache line - 记住:64 字节 cache line 是硬约束,
alignas(64)和结构体字段重排,比调任何 perf 参数都管用
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











