CPU cache 与 NUMA¶
是什么 / 解决什么问题¶
低延迟程序经常不是算力不足,而是 CPU 在等内存。cache miss、false sharing、NUMA 远端访问会把纳秒级逻辑放大成微秒级抖动。
核心模型¶
典型访问成本从低到高:
| 层级 | 大致量级 | 说明 |
|---|---|---|
| L1 cache | ~1ns | 当前核心私有 |
| L2 cache | 数 ns | 当前核心私有或局部共享 |
| L3 cache | 十几 ns | socket 内共享 |
| 本地 DRAM | 数十到百 ns | 当前 NUMA node |
| 远端 DRAM | 更高且抖动更大 | 跨 socket 访问 |
具体数值依赖硬件,面试时不要背死数字,重点讲数量级和排查方法。
false sharing¶
多个线程更新不同变量,但变量落在同一 cache line,会导致 cache line 在核心之间反复失效。
struct counters_bad {
uint64_t rx_count;
uint64_t tx_count;
};
struct counters_good {
alignas(64) uint64_t rx_count;
alignas(64) uint64_t tx_count;
};
alignas(64) 不是万能解,真实项目还要确认结构体数组、allocator 对齐和字段布局。
NUMA 原则¶
- 线程固定到 CPU
- 内存由使用它的线程初始化
- NIC queue、中断、业务线程尽量在同一个 NUMA node
- 避免跨 socket 共享热数据
观测与调试¶
lscpu
numactl --hardware
numastat -p <pid>
perf stat -e cache-misses,cache-references ./app
perf mem record ./app
perf mem report
面试高频问题¶
怎么判断程序是 cache 问题¶
看 IPC、cache miss、内存访问热点和数据结构布局。perf stat 里 IPC 很低且 cache miss 高,说明 CPU 可能在等待内存;再用 perf record、perf mem 定位热点。
怎么降低 cache miss¶
让热数据更小、更连续、更少指针跳转;拆冷热字段;避免在热路径使用链表和树;预分配对象;减少跨线程共享。