TLB 是什么?地址翻译的缓存,miss 才是性能杀手;内存对齐管好边界
答案:TLB 缓存"虚拟地址→物理地址"的翻译,miss 会拖慢程序;内存对齐让数据落在单一 cache line/页内,避免跨行跨页开销。两者都影响"一次内存访问的实际代价"。
TLB:CPU 的地址翻译缓存
虚拟地址 ──► TLB(命中:直接拿到物理地址)──► 内存
│ miss
▼
页表逐级查询(慢几十~几百周期)- TLB 容量有限:通常几十到几百条,只覆盖近期访问的页面;
- TLB miss 代价大:要走页表(多级内存),最坏几百周期;
- 典型症状:程序访问步长/地址分散,导致跨页过多 → TLB 频繁 miss → 性能断崖。
如何发现:perf stat -e dTLB-load-misses,itlb-load-misses ./app;或做步长实验(迭代次数不变只改步长,性能在某点骤降 → 就是 TLB,参见 tlb-thrashing 实验)。
内存对齐:数据别跨边界
对齐 = 变量地址是其大小的整数倍(8 字节类型在 8 的倍数地址)。为什么重要:
- 原子性:对齐的 8 字节读写不会被拆成两次总线事务;
- 避免跨 cache line:不对齐的数据可能横跨两个 64 字节 cache line,一次访问要搬两行;
- 避免跨页:跨页的访问天然增加 TLB/页表开销;
- 避免伪共享:让不同线程的数据对齐到不同 cache line(配合 MESI 那篇)。
设置方式:
alignas(64) int a; // C++11
int __attribute__((aligned(64))) b; // GCC
posix_memalign(&p, 64, size); // 运行时分配深度入口
- TLB 实验与原理:TLB 与地址翻译
- 缓存组织与 cache line:缓存组织
- 可运行实验:tlb-thrashing
FAQ
Q: TLB 是什么? A: TLB(Translation Lookaside Buffer)是 CPU 里的地址翻译缓存,缓存"虚拟地址→物理地址"的映射,避免每次访问内存都走页表查询。
Q: TLB miss 会怎样? A: TLB miss 要走页表(多级内存访问),一次 miss 可能拖慢几十到几百周期。程序访问跨页太多页时 TLB 频繁 miss,性能骤降。
Q: 怎么看出程序有 TLB 问题? A: perf stat 看 dTLB-load-misses 等事件;或对比不同访问步长的性能(步长增大到跨页时出现断崖,如 tlb-thrashing 实验)。
Q: 内存对齐是什么? A: 内存对齐是让变量地址落在其大小整数倍上(如 8 字节类型对齐到 8 字节地址),保证单次访存、原子性,并避免跨 cache line 拆分。
Q: 对齐和 TLB 有什么关系? A: 对齐保证数据落在单一 cache line/页内,减少"一次访问跨两行/两页"的开销;cache line 对齐还能避免伪共享(见 MESI)。
Q: 怎么设置内存对齐? A: C/C++ 用 alignas(64) / __attribute__((aligned(64))) / posix_memalign;结构体里注意字段顺序减少 padding 浪费;编译器默认对齐即可。
一句话总结:TLB 缓存地址翻译、miss 才是大开销;内存对齐让数据待在单一 cache line/页内;两者共同决定"一次访存到底多贵",用 perf stat 的 TLB miss 事件和步长实验来验证。