malloc 分配 free 释放 MADV_FREE MADV_DONTNEED/munmap
malloc 分配 free 释放 MADV_FREE MADV_DONTNEED/munmap
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Active │───────▶│ Dirty │────────▶│ Muzzy │────────▶│ Retained│
│ (使用中) │ │ (刚释放) │ │(半归还OS)│ │ (已归还OS)│
└─────────┘ └─────────┘ └─────────┘ └─────────┘
复用最快 复用较快 需重新mmap
算在RSS 算在RSS* 不算在RSS
* Muzzy 页仍映射在进程地址空间,算在 RSS 中,但 OS 可在内存压力时直接收回(不需要进程参与)。
dirty_decay_ms 的作用
控制 Dirty → Muzzy 的转换速度。
free 后的页进入 Dirty pool
│
│ dirty_decay_ms = 5000
│ → 如果 5 秒内没被复用,jemalloc 调用 madvise(MADV_FREE)
│ 将其降级为 Muzzy
│
▼
Dirty page → Muzzy page
具体机制:jemalloc 每个 arena 有一个 dirty page 的”时间轴”(PQ,优先队列按释放时间排序)。每过 dirty_decay_ms 毫秒,后台线程扫描一次,把超过 decay 时间没被复用的 dirty page 调用 MADV_FREE 降级。
对性能的影响:
- Dirty page 复用是零开销的(直接返回指针,无系统调用)
- decay 越长 → dirty pool 越大 → 命中复用概率越高 → malloc 越快
- decay 越短 → dirty page 快速降级为 muzzy → RSS 更低但复用命中率下降
muzzy_decay_ms 的作用
控制 Muzzy → Retained(归还 OS) 的转换速度。
Muzzy page(已被 MADV_FREE,OS 可回收)
│
│ muzzy_decay_ms = 1000
│ → 如果再过 1 秒没被复用,jemalloc 调用 madvise(MADV_DONTNEED)
│ 或 munmap,真正归还给 OS
│
▼
Muzzy page → Retained(从 RSS 移除)
具体机制:与 dirty decay 类似,后台线程定期扫描 muzzy pool,超过 decay 时间的页被 MADV_DONTNEED(Linux 下页表项清零,物理页立即归还,但虚拟地址保留)。
对性能的影响:
- Muzzy page 复用需要一次 minor page fault(~1-2μs),比 dirty 慢但仍远快于 mmap
- decay 越长 → muzzy pool 越大 → 复用时可能避免 page fault
- decay 越短 → 页快速归还 OS → RSS 最低但需要时重新分配