首页/系统/Linux 内核与性能调优速查/MADV_HUGEPAGE 按需启用大页
内存与 OOM58 条

MADV_HUGEPAGE 按需启用大页

应用对特定内存区间声明 MADV_HUGEPAGE 启用、MADV_NOHUGEPAGE 关闭 THP,在全局 always 之外获得按需控制能力。

按需启用大页

应用可以对特定内存区间调用 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 统计确认实际命中,而不是凭推测判断
同一进程内可以对不同区间采取不同策略:热数据区声明大页、对延迟敏感的队列区关闭大页,按区域粒度做权衡。

易错点

  • 全局 never 下仍期待生效:调用被忽略,应先调整全局设置
  • 区间未对齐:合并成功率低,误以为接口无效
  • 不做验证:应通过 smaps 的 AnonHugePages 确认实际命中情况
  • 只声明部分区域却期望整进程生效:声明是区间级的
  • 忽略 defrag 设置:声明之后仍需整理才能凑出大页

数据来源与参考

  • man-pages madvise(2)
  • Linux 内核 Documentation/admin-guide/mm/transhuge.rst
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌