4. 透明大页(THP)机制
透明大页(Transparent Hugepages,THP)是 Linux 内核提供的一种自动化内存管理特性,旨在无需应用程序修改的情况下,利用大页(通常为 2MB)降低 TLB 未命中率,提升内存密集型工作负载的性能。THP 的核心价值在于“透明”——对用户态进程完全无感,内核自动完成大页的分配、合并与拆分。
4.1 THP 的工作原理
THP 在内核内存管理子系统(主要是 mm/huge_memory.c)中实现,其工作流程可概括为以下三个阶段:
- 机会性分配(Opportunistic Allocation):当进程通过
mmap、malloc或缺页异常申请内存时,内核会尝试分配连续的 2MB 物理页面(即透明大页),而非默认的 4KB 小页。分配成功则直接映射为一个大页表项(PTE),减少页表层级。 - 后台合并(Khugepaged 内核线程):对于已经使用 4KB 小页映射的内存区域,内核线程
khugepaged会定期扫描,尝试将物理地址连续的 512 个小页合并为一个 2MB 大页。合并操作会更新页表,并释放中间页表层级。 - 按需拆分(Partial Splitting):当大页中的某个子页需要被换出、迁移或进行写时复制(COW)时,内核会将这个大页拆分为 512 个 4KB 小页,以保证操作粒度的灵活性。
关键指标: THP 的分配成功率直接影响 TLB 覆盖范围。在 2MB 大页下,单条 TLB 条目可覆盖 2MB 连续内存,相比 4KB 小页覆盖范围提升 512 倍。
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 拆分对延迟稳定性的影响。
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 后,建议观察至少一个业务周期以确认稳定性。