按需启用大页
应用可以对特定内存区间调用 madvise 声明大页期望:MADV_HUGEPAGE 表示该区间尽量使用透明大页,MADV_NOHUGEPAGE 表示该区间不要使用。这样在全局 always 之外获得按需控制能力,也让全局选 madvise 模式时应用可以主动声明。效果依赖分配的对齐与访问模式,2MiB 对齐的大块更容易被合并为大页,可用 /proc/<pid>/smaps 的 AnonHugePages 字段验证。
基本信息
| 接口 | madvise(2) |
|---|---|
| 启用大页 | MADV_HUGEPAGE |
| 关闭大页 | MADV_NOHUGEPAGE |
| 验证 | /proc/<pid>/smaps 的 AnonHugePages |
| 生效前提 | 全局 THP 为 always 或 madvise |
典型使用场景
- 大型堆或缓存区希望使用大页减少 TLB 缺失
- 对时延敏感的区域不希望被合并成大页
- 在全局 madvise 模式下主动声明需要的区间
- 排查声明之后大页仍不生效的原因
- 与静态大页方案做对比选择
C 调用与验证
C 调用与验证
madvise(addr, len, MADV_HUGEPAGE); // 该区间尽量使用透明大页
madvise(addr, len, MADV_NOHUGEPAGE); // 该区间不使用透明大页
// 验证:统计进程已使用的匿名大页总量
grep -i 'AnonHugePages' /proc/<pid>/smaps | awk '{s+=$2} END {print s " kB"}'
grep -c -i 'AnonHugePages' /proc/<pid>/smaps // 有多少个区间命中生效条件
| 全局设置 | 声明的效果 | 说明 |
|---|---|---|
| enabled=always | 声明后更容易命中 | 默认就尝试合并大页 |
| enabled=madvise | 仅声明的区间使用大页 | 可控性最好 |
| enabled=never | 声明也不生效 | 全局关闭优先级更高 |
| 区间对齐 | 2MiB 对齐更易命中 | 未对齐会降低合并成功率 |
大块分配未按 2MiB 对齐时合并命中率低,应用侧的数据结构布局与分配方式会直接影响效果。
madvise 声明只在全局 THP 为 always 或 madvise 时才有意义,never 模式下调用会被忽略。
效果不佳时的检查顺序
- 先确认全局 enabled 不是 never,否则声明不会产生任何效果
- 检查申请的内存是否按 2MiB 对齐,未对齐会显著降低命中率
- 确认 defrag 允许整理,否则仍然凑不出大页
- 用 smaps 的 AnonHugePages 统计确认实际命中,而不是凭推测判断
同一进程内可以对不同区间采取不同策略:热数据区声明大页、对延迟敏感的队列区关闭大页,按区域粒度做权衡。