缓存未命中率高导致数组访问慢,八成因数据未进L1缓存;用perf record -e cache-misses,cache-references定位高占比函数,需-O2/-O3编译防优化失真,并检查内存步长是否破坏预取器。

用 perf record -e cache-misses,cache-references 捕获缓存未命中率
数组访问慢,八成不是 CPU 算得慢,而是数据没进 L1 缓存。直接看硬件事件比猜更准:perf record -e cache-misses,cache-references ./myapp 跑完后 perf report 会标出哪些函数的 cache-misses 占比异常高。注意:必须在 -O2 或 -O3 下测试,否则编译器可能把整个循环优化掉,测出来是 0 —— 这不是快,是假数据。
检查内存访问步长是否破坏硬件预取器
现代 CPU 的预取器对固定步长很敏感。比如 for (int i = 0; i 这种跳着读,L1 预取器大概率失效,<code>perf stat -e mem-loads,mem-stores 会显示大量 mem-loads 命中不到缓存。真正友好的是连续地址访问(步长=1),或至少步长 ≤ 缓存行大小(通常 64 字节)。验证方法:把 i += 8 改成 i += 1,再跑一次 perf stat 对比 cache-misses 变化。
确认数组布局是否导致 false sharing(伪共享)
多线程写不同元素却卡住?很可能多个线程在改同一缓存行里的不同数组项。例如 std::array<int> arr;</int>,64 个 int 刚好占满一行(64 字节),线程 A 写 arr[0]、线程 B 写 arr[1],就会反复使对方的缓存行失效。现象是 perf stat -e l1d.replacement 数值飙升。解决办法:用填充(padding)让每个热点元素独占缓存行,或改用 alignas(64) 对齐结构体字段。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
避免 volatile 干扰真实性能判断
写微基准时有人加 volatile 防优化,但这也同时禁掉了编译器的向量化和 prefetch hint。结果测出来的是“强制不优化路径”的速度,不是实际运行态。真要测数组遍历性能,应保持代码自然形态,靠 benchmark::DoNotOptimize() 或写入全局变量来防止死码消除,而不是靠 volatile 锁死访存模式。
立即学习“C++免费学习笔记(深入)”;
数组访问的瓶颈往往藏在缓存行边界、预取器行为和多线程协同方式里,而不是下标计算本身。盯着cache-misses 和 l1d.replacement 这两个计数器,比看函数耗时更接近真相。


















