4、透明大页(THP)机制

透明大页(Transparent Hugepages,THP)是 Linux 内核提供的一种自动化内存管理特性,旨在无需应用程序修改的情况下,利用大页(通常为 2MB)降低 TLB 未命中率,提升内存密集型工作负载的性能。THP 的核心价值在于“透明”——对用户态进程完全无感,内核自动完成大页的分配、合并与拆分。

4.1 THP 的工作原理

THP 在内核内存管理子系统(主要是 mm/huge_memory.c)中实现,其工作流程可概括为以下三个阶段:

  1. 机会性分配(Opportunistic Allocation):当进程通过 mmap、malloc 或缺页异常申请内存时,内核会尝试分配连续的 2MB 物理页面(即透明大页),而非默认的 4KB 小页。分配成功则直接映射为一个大页表项(PTE),减少页表层级。
  2. 后台合并(Khugepaged 内核线程):对于已经使用 4KB 小页映射的内存区域,内核线程 khugepaged 会定期扫描,尝试将物理地址连续的 512 个小页合并为一个 2MB 大页。合并操作会更新页表,并释放中间页表层级。
  3. 按需拆分(Partial Splitting):当大页中的某个子页需要被换出、迁移或进行写时复制(COW)时,内核会将这个大页拆分为 512 个 4KB 小页,以保证操作粒度的灵活性。
关键指标: THP 的分配成功率直接影响 TLB 覆盖范围。在 2MB 大页下,单条 TLB 条目可覆盖 2MB 连续内存,相比 4KB 小页覆盖范围提升 512 倍。
透明大页(THP)工作流程 THP 工作流程:分配 → 合并 → 拆分 进程内存申请 mmap / malloc / 缺页 机会性分配 尝试分配 2MB 连续页 Khugepaged 合并 512×4KB → 1×2MB 按需拆分 换出 / COW / 迁移 说明:分配路径(实线)优先尝试大页;合并路径(虚线)由 khugepaged 后台异步完成;拆分路径在内存操作冲突时触发。

4.2 自动合并与拆分策略

4.2.1 Khugepaged 合并策略

khugepaged 是内核中负责扫描和合并内存的守护线程。其合并策略受以下参数控制:

参数 默认值 说明
pages_to_scan 4096 每次唤醒扫描的页面数,值越大合并速度越快,但 CPU 开销也越高。
scan_sleep_millisecs 10000 两次扫描之间的休眠时间(毫秒),减少对前台进程的干扰。
alloc_sleep_millisecs 60000 分配大页失败后的重试等待时间(毫秒)。
max_ptes_none 511 允许合并区域中未映射页表项的最大数量,控制合并的激进程度。

合并触发条件:

  • 目标虚拟内存区域(VMA)必须支持大页(如匿名内存、共享内存)。
  • 物理地址必须连续,且所有子页的引用计数一致。
  • 区域内不能有被锁定(mlock)或正在被内核使用的页面。

4.2.2 拆分策略

拆分操作由内核在以下场景中自动触发:

  • 页面换出(Swap Out):当内存压力增大,内核需要将页面换出到交换分区时,必须将大页拆分为小页,因为交换子系统以 4KB 为基本单位。
  • 写时复制(COW):当 fork() 后的父子进程对共享大页中的某一页执行写操作时,内核会拆分大页,仅复制被修改的 4KB 子页。
  • 内存迁移(Migration):在 NUMA 平衡或内存规整(Compaction)过程中,大页可能被拆分为小页以支持更细粒度的迁移。
  • 碎片整理(Defragmentation):当系统无法分配连续 2MB 物理内存时,内核会触发内存规整,期间可能拆分已有大页以释放更小的连续块。
性能陷阱: 频繁的拆分与再合并会导致页表操作开销剧增,并可能引发内存碎片。在数据库或实时系统中,建议评估 THP 拆分对延迟稳定性的影响。
THP 合并与拆分状态机 THP 页面状态转换:4KB 小页 ↔ 2MB 大页 4KB 小页 512 个独立 4KB 页 2MB 大页 单一大页表项 khugepaged 合并 换出 / COW / 迁移 触发拆分 注意:合并是后台异步操作,拆分是同步操作。拆分后的小页可能被再次合并,形成“合并-拆分”震荡,增加 CPU 开销。

4.3 THP 的 sysfs 控制接口

Linux 内核通过 /sys/kernel/mm/transparent_hugepage/ 目录下的 sysfs 文件提供 THP 的运行时控制能力。管理员可以通过读写这些文件动态调整 THP 行为,无需重启系统。

4.3.1 核心控制文件

文件路径 可选值 说明
/sys/kernel/mm/transparent_hugepage/enabled always / madvise / never 全局 THP 启用策略。always 对所有 VMA 启用;madvise 仅对显式调用 madvise(MADV_HUGEPAGE) 的区域启用;never 完全禁用。
/sys/kernel/mm/transparent_hugepage/defrag always / defer / defer+madvise / madvise / never 内存规整(defrag)触发策略,控制内核在分配大页失败时是否主动整理内存碎片。
/sys/kernel/mm/transparent_hugepage/khugepaged/max_ptes_none 0–511 控制 khugepaged 合并的激进程度。值越小,合并条件越严格。
/sys/kernel/mm/transparent_hugepage/shmem_enabled always / within_size / advise / never / deny / force 控制共享内存(tmpfs/shmem)是否使用 THP。

4.3.2 配置示例

以下命令展示如何在不同场景下调整 THP 行为:

# 完全禁用 THP(适用于延迟敏感型应用,如数据库)
echo never > /sys/kernel/mm/transparent_hugepage/enabled

# 仅对显式声明的大页区域启用(推荐用于混合负载)
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled

# 设置 defrag 为 defer+madvise:仅在 madvise 区域主动规整,其他区域延迟规整
echo defer+madvise > /sys/kernel/mm/transparent_hugepage/defrag

# 查看当前 THP 状态
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag

4.3.3 策略选择建议

工作负载类型 推荐 enabled 值 推荐 defrag 值 理由
HPC / 科学计算 always always 大页显著提升 TLB 命中率,内存规整开销可接受。
数据库(MySQL/PostgreSQL) madvise defer+madvise 避免全局 THP 导致的延迟抖动,仅在关键缓冲区使用大页。
实时系统 / 嵌入式 never never 消除 THP 拆分和规整带来的不可预测延迟。
云原生 / 容器化 madvise madvise 兼顾多租户隔离与性能,由应用显式控制大页使用。
调优技巧: 使用 grep AnonHugePages /proc/meminfo 监控系统级 THP 使用量;使用 perf stat -e dTLB-load-misses 评估 THP 对 TLB 未命中的改善效果。在调整 enabled 或 defrag 后,建议观察至少一个业务周期以确认稳定性。
THP sysfs 控制接口结构 THP sysfs 控制接口层次 /sys/kernel/mm/transparent_hugepage/ enabled defrag khugepaged/ shmem_enabled 提示:修改 enabled 和 defrag 立即生效,无需重启;khugepaged/ 下包含 pages_to_scan 等子参数。