--- tags: aliases: - 1. 宏观原理图:箱子与积木的错位 date created: 星期一, 十一月 24日 2025, 5:50:26 下午 date modified: 星期一, 十一月 24日 2025, 5:50:35 下午 --- # 1. 宏观原理图:箱子与积木的错位 想象 CPU 是一个强迫症收纳师,他手里有一排固定的收纳盒(缓存行),每个盒子长度固定是 64。 我们要存的数据(点迹) 是长度为 48 的积木条。 请看下面的图,展示了当我们把积木一条接一条紧挨着放进去时,发生了什么: ```mermaid --- config: theme: base flowchart: curve: linear --- graph LR %% 样式定义 classDef box fill:#e6f7ff,stroke:#1890ff,stroke-width:2px,stroke-dasharray: 5 5 classDef block1 fill:#ffccc7,stroke:#f5222d,stroke-width:2px classDef block2 fill:#d9f7be,stroke:#52c41a,stroke-width:2px subgraph Memory["内存空间 (连续摆放)"] direction LR subgraph Box1["收纳盒 1 (容量 64)"] direction LR A1["积木A (48)"]:::block1 B1["积木B 的头 (16)"]:::block2 end subgraph Box2["收纳盒 2 (容量 64)"] direction LR B2["积木B 的身子 (32)"]:::block2 C1["…"]:::white end end %% 解释连接 A1 -- 紧挨着 --> B1 B1 -- "⚠️ 惨遭腰斩 ⚠️" --> B2 ``` # 2. 细节文字表述:为什么这很糟糕? **场景还原:** 1. **强迫症规则**:CPU 每次读取数据,必须**连盒带盖**端走整整一个“收纳盒”(64 字节),不能只捏走里面的某一块。 2. **读取积木 A(红色)**: - CPU 伸手端走 **收纳盒 1**。 - 积木 A 完整地在盒子里。 - **耗时**:1 次搬运。**(快)** 3. **读取积木 B(绿色)**: - CPU 端走 **收纳盒 1**,拿到了积木 B 的**头**。 - CPU 发现身子没了,只能再去端走 **收纳盒 2**,拿到积木 B 的**身子**。 - 然后 CPU 还得在手里把这两段拼起来。 - **耗时**:2 次搬运 + 拼接时间。**(慢!)** # 3. 结论与解决方案 - **问题核心**:因为数据的尺寸(48)不能被盒子的尺寸(64)整除,导致后续的数据像“跨栏”一样骑在两个盒子的边界上。这叫**跨缓存行(Cache Line Split)**。 - **我们的方案(填充 Padding)**: - 既然 48 放不进 64 很尴尬,我们就在每个积木后面**硬塞 16 块没用的泡沫(Padding)**。 - 把积木强行撑大到 **64**。 - **结果**:虽然浪费了空间,但现在每个盒子正好放一个积木。CPU 拿任何积木都只需要搬 **1 次**盒子。 这就是我们为了极致性能所做的妥协:**用空间换时间**。