直接回答:大页把页面尺寸从默认 4KB 扩大到 2MB 或 1GB,目的是摊薄地址翻译开销:同样 1GB 内存,4KB 页需要约 26 万个页表项,2MB 页只需 512 个,TLB 覆盖率提升数百倍,缺页次数和页表层级也相应减少,同时一次 page walk 要走的页表项也少了,缺页处理的开销随之摊薄,对数据库、JVM 这类大内存应用收益明显。
展开解析:Linux 提供两种机制。hugetlbfs 是显式预留式:通过 vm.nr_hugepages 启动时划出固定数量大页,应用经 mmap(MAP_HUGETLB) 或 System V 共享内存使用,行为确定、不可换出。THP(透明大页)则由内核自动把匿名页合并晋升,后台 khugepaged 线程负责扫描。THP 的问题在于:晋升与拆分会触发内存规整(compaction),NUMA 机器上容易造成几十毫秒的延迟尖刺;碎片严重时效果反而更差,且大页参与 swap 路径复杂。
实践要点:Redis、MongoDB、Oracle 官方都建议关闭 THP:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
需要大页的场景改用 hugetlbfs 显式分配。折中是把 enabled 设为 madvise,只让显式调用 madvise(MADV_HUGEPAGE) 的内存区域使用大页。
追问方向:THP 的 madvise 模式语义是什么?大页对 fork 的写时复制有什么影响?为什么大页能减少缺页次数却未必降低单次缺页成本?