缓存与局部性
CACHE & THE LOCALITY PRINCIPLE // 快的东西,都是被复用的东西
> CPU 比内存快 100 倍,内存比磁盘快 10 万倍——计算机却没有瘫痪,靠的是一个赌注:程序会反复访问刚访问过的东西(时间局部性),以及它旁边的东西(空间局部性)。缓存就是把赌注变成硬件:小而快的层,存放"可能马上再用"的少数。整个存储金字塔、CDN、Redis、浏览器缓存、CPU L1/L2/L3,全是同一条定律的化身:复用即加速。
Principle — 原理与来源
理论奠基:彼得·丹宁(Peter J. Denning)1968 年在虚拟内存研究中提出工作集模型(working set)并系统化"访问局部性"原理——程序在任意时刻真正活跃的页面只有一小簇(工作集),且簇随时间缓慢漂移。更早的思想源头:Wilkes 1965提出带"slave memory"的层次存储设想;1968 年 IBM System 360/85首次商用缓存并把 "slave memory" 更名为 cache(法语"隐藏的储藏处")。Denning 后来说:局部性原理"从虚拟内存的挣扎中诞生,最终统治了计算的一切层"。
两类局部性:① 时间局部性——刚被引用的信息很快再被引用(循环变量、热点函数、最近打开的文件);② 空间局部性——刚被引用的邻近信息很快被引用(数组顺序遍历、指令顺序执行)。衍生的工程手段:预取(prefetch,赌空间)、替换策略(LRU/FIFO,赌时间)。缓存的一切设计,都是对这两句话下注。
核心公式(AMAT):平均访问时间 = 命中时间 + 未命中率 × 未命中代价。命中 1ns、未命中 100ns 时:90% 命中 → 1+0.1×100=11ns;99% 命中 → 2ns;99.9% → 1.1ns。命中率每多一个 9,性能上一个数量级——这就是为什么缓存工程师为一个百分点拼命。
无处不在的分层:寄存器 → L1/L2/L3 → 内存 → SSD → 磁盘 → 网络(CDN/Redis/浏览器缓存);甚至 TLB 缓存地址翻译、branch predictor 缓存分支历史、DNS 缓存、你桌上的常用文件夹——只要存在"访问不均 + 重访概率 + 层间速度差",缓存就会出现。它是帕累托法则的硬件化:少数数据承载多数访问。
Apply — 用在哪里
Simulate — 命中率计算器 × 访问模式实验
Personal Takeaways — 个人启示 · 03
速度来自复用,不来自更快
存储金字塔每一层都没有"消灭"慢层,只是在它前面加了一个赌局。性能工程的本质不是买更快的硬件,是提高重访率——你的代码、架构、工作流同理:先问"什么在被反复计算/反复获取",答案就是你的缓存候选。
命中率是乘法世界的杠杆
AMAT 公式的残酷在于未命中率乘以惩罚:惩罚越大(网络 vs 内存、磁盘 vs 内存),命中率的每一个 9 越值钱。先看访问断层有多大,再决定为命中率投入多少——在断层小的地方死磕缓存,是优化的常见错位。
整理你的人生缓存层级
局部性原理对人也成立:常用物上手边、常访信息进收藏、常走路线做成例程。时间管理的秘诀不在"更快地找",而在"把高频搬近"——每周回顾你的"访问日志",重新摆放你的 L1。