内存本质:从比特到指针

原理

DRAM 每个位元为 1T1C(1 transistor + 1 capacitor),电容充电=1,放电=0。因电容漏电需刷新(~64ms 周期)。SRAM 使用 6T 触发器存储,无需刷新,延迟极低(~1ns),用于 CPU 缓存。

内存层次结构:

层级技术大小延迟Rust 对应
寄存器触发器~1KB0.3ns局部变量
L1 缓存SRAM32KB1ns热数据
L2 缓存SRAM256KB4ns当前工作集
L3 缓存SRAM8-32MB12ns跨核共享
主存DRAMGB100nsVec 堆分配
磁盘NANDTB10-100μsFile::read

虚拟内存通过 MMU 将虚拟地址转为物理地址,页表为 4 级结构(x86_64 使用 48 位有效 VA)。TLB 是 MMU 内部缓存,命中则转换零开销,未命中需 4 次内存读(~400ns)。

Rust 启示:Vec 连续内存使 CPU 预取器有效利用缓存行(64B),LinkedList 因随机指针追逐导致 TLB 抖动和缓存未命中。


语法

Rust 内存操作

use std::mem;
 
let v: Vec<i32> = vec![1, 2, 3];
println!("size: {}", mem::size_of::<Vec<i32>>());  // 24 (ptr+len+cap)
println!("align: {}", mem::align_of::<i32>());     // 4
 
// 栈上固定大小
let arr: [i32; 3] = [1, 2, 3];
 
// 堆上通过 Box 分配
let b: Box<i32> = Box::new(42);
let raw: *const i32 = &*b;  // 获取底层指针

内存布局

类型栈大小堆数据Copy?
i324B
&[T]16B (ptr+len)在引用对象上
String24B (ptr+len+cap)UTF-8 字节
Vec<T>24B (ptr+len+cap)T 数组
Box<T>8B (ptr)T
dyn Trait16B (data+vtable)取决于实现

实践

力扣问题

力扣: 力扣斐波那契题 — 注意内存消耗

fn fib(n: u32) -> u64 {
    let mut a = 0u64;
    let mut b = 1u64;
    for _ in 0..n { let t = b; b = a + b; a = t; }
    a
}

AI 自检

  1. x86_64 虚拟地址为何只用 48 位而非 64 位?剩余 16 位的作用?
  2. Vec 连续内存为何比 LinkedList 高效?从缓存行(64B)和 TLB 角度解释。