TLB
Outlinks (0)
No outlinks found
Backlinks (0)
No backlinks found
1 · TLB#
1.1 · S 什么场景#
现代 CPU 使用虚拟内存:每个进程看到的地址都是虚拟地址,必须通过页表(page table) 翻译成物理地址才能真正访问内存。
页表存在主存里,本身就是多级结构(x86-64 通常 4 级)。这意味着每次内存访问都要先做一次 page walk——沿着页表树走 4 次内存读——才能拿到物理地址,然后才去访问目标数据。
一次普通内存访问,变成了 5 次。
1.2 · C 什么冲突#
冲突在于:虚拟内存提供了隔离和灵活性,但 page walk 的代价让它变得不可接受地慢。
- 想要隔离和安全:每个进程有独立地址空间,互不干扰
- 想要性能:不希望每次内存访问都额外付出 4 次主存读取的延迟
如果每次访存都做完整 page walk,CPU 大部分时间花在”查地址”而不是”用数据”上。
1.3 · Q 什么问题#
1.3.1 · 1. TLB 是什么?#
TLB(Translation Lookaside Buffer)是 MMU 中的一个硬件缓存,缓存最近使用过的虚拟地址 → 物理地址映射。
- 本质上是一个小型的、用 CAM(Content-Addressable Memory)实现的关联缓存
- 输入虚拟页号(VPN),输出物理帧号(PFN)
- 命中时只需 1 个时钟周期,完全在流水线内完成
1.3.2 · 2. TLB hit 和 TLB miss 分别发生什么?#
TLB hit:虚拟页号在 TLB 中找到对应条目,直接拿到物理帧号,拼上页内偏移即可访问物理内存。代价约 1 个周期。
TLB miss:TLB 中没有这个映射,需要做 page walk:
- 硬件(x86)或软件(MIPS)遍历多级页表
- 找到有效的页表项 → 把映射加载到 TLB,重试访问
- 如果页表中 present bit 也没设置 → 触发 page fault,由 OS 处理(可能要从磁盘换入页面)
TLB miss 的代价远大于普通 cache miss,因为 page walk 本身就需要多次内存访问。
1.3.3 · 3. TLB miss 由谁处理?#
三种方案:
| 方案 | 代表架构 | 特点 |
|---|---|---|
| 硬件管理 | x86(CR3 寄存器指向页表根) | CPU 自动 walk 页表,对软件透明 |
| 软件管理 | MIPS, SPARC | TLB miss 触发异常,由 OS 代码填充 TLB |
| 固件管理 | Alpha(PALcode) | 类似软件管理,但由固件处理,允许不同 OS 用不同页表格式 |
x86 用硬件管理,好处是简单且快;软件管理的好处是灵活(OS 可以自定义页表格式和替换策略)。
1.3.4 · 4. TLB 的典型结构是什么样?#
现代 CPU 通常有多级 TLB,类似 L1/L2 cache 的分层:
- L1 ITLB(指令)+ L1 DTLB(数据):小、快、低延迟
- L2 TLB:统一的、更大的 TLB,L1 miss 后查这里
以 Intel Nehalem 为例:
- L1 DTLB:64 条目(4 KiB 页),4 路组相联
- L1 ITLB:128 条目(4 KiB 页),4 路组相联
- L2 TLB:512 条目(4 KiB 页),4 路组相联,指令数据统一
1.3.5 · 5. 上下文切换时 TLB 怎么办?#
进程切换意味着地址空间变了,TLB 中旧进程的映射不再有效。最简单的做法是整体刷新(flush),但代价很高——新进程刚切进来时 TLB 全空,每次访存都是 miss。
优化手段:
- ASID(Address Space Number):每个 TLB 条目带上地址空间标识,只有 ASID 匹配当前进程的条目才有效。切换时不需要 flush,只需切换 ASID
- PCID(Process-Context Identifier, x86):Intel 从 Westmere 开始支持的 12-bit 标识符,允许 TLB 同时保留多个进程的映射
- Global 页:标记为 global 的页(如内核映射)在切换时不被刷新
Linux 4.14 开始利用 PCID 避免不必要的 TLB flush,这在 Meltdown/Spectre 补丁(KPTI)后对性能尤为重要。
1.3.6 · 6. 大页(Huge Pages)为什么能减少 TLB miss?#
TLB 条目数量有限(通常几十到几百个)。如果页大小是 4 KiB,512 个 TLB 条目只能覆盖 2 MiB 的内存。
使用大页(x86 上 2 MiB 或 1 GiB)时:
- 同样数量的 TLB 条目可以覆盖更大范围的内存
- 32 个 2 MiB 大页条目就能覆盖 64 MiB
- page walk 也更短(少一级页表)
适用场景:数据库、JVM、大内存工作集的应用。
1.3.7 · 7. TLB 与 CPU cache 的关系?#
TLB 的位置决定了 cache 使用物理地址还是虚拟地址:
- 物理地址缓存(PIPT):每次访存先查 TLB 拿物理地址,再用物理地址查 cache。正确性好,但 TLB 在关键路径上
- 虚拟地址缓存(VIVT):直接用虚拟地址查 cache,cache miss 时才查 TLB。更快,但有同义词/同名问题
- 常见优化(VIPT):用虚拟地址的 index 位查 cache(与 TLB 并行),用物理地址的 tag 位做比对。兼顾速度和正确性
现代 x86 的 L1 cache 通常用 VIPT:TLB 查找和 cache 查找并行进行,不会增加额外延迟。
1.4 · A 回答问题#
TLB 是 MMU 中缓存”虚拟地址 → 物理地址”映射的硬件缓存,把原本需要 4 次内存访问的 page walk 压缩到 1 个周期完成。
关键理解点:
- TLB 解决的是 page walk 太慢的问题,不是 cache miss 的问题
- TLB miss 比普通 cache miss 更贵,因为 page walk 本身要多次访存
- TLB 条目数量极少(几十~几百),所以覆盖范围有限,大页是直接的优化手段
- 上下文切换是 TLB 性能的大敌,ASID/PCID 是避免全量 flush 的关键技术
- 现代 CPU 用 VIPT 让 TLB 查找和 L1 cache 查找并行,消除了额外延迟