1. 概述
透明大页(Transparent Huge Pages,简称THP)是Linux内核提供的一项优化内存管理性能的机制。
它通过将默认的4KB小页,在满足条件的情况下自动合并为较大的页(通常为2MB),以减少页表项数量、提升TLB(Translation Lookaside Buffer,快表)命中率,从而降低内存访问开销,改善系统整体性能。
2. 相关配置
2.1 功能开关
THP的功能开关控制系统是否启用透明大页功能。
配置路径:
/sys/kernel/mm/transparent_hugepage/enabled
参数选项说明:
always:所有合适的内存分配都尽可能使用大页。madvise:仅当程序显式通过madvise()系统调用请求时才使用大页。
2.2 碎片整理
由于大页分配需要连续的物理内存区域,长时间运行的系统往往因频繁分配和释放导致内存碎片化。碎片整理(defragmentation)是指内核通过页面迁移等手段合并零散的物理页,从而形成足够大的连续区域用于大页分配。碎片整理可能会导致系统延迟上升,特别是在前台执行时。
配置路径:
/sys/kernel/mm/transparent_hugepage/defrag
参数选项说明:
always:当前线程始终等待内核整理碎片后再分配大页,可能严重影响响应时间。defer:当前线程不会等待,碎片整理在后台异步执行。madvise:仅针对显式调用madvise()请求的内存区域进行整理。defer+madvise:当前线程不等待,碎片整理交给后台,仅针对明确请求使用大页的内存。never:完全不整理碎片,若无法直接分配大页,则回退为小页。
2.3 后台合并线程
khugepaged是内核中的后台线程,定期扫描匿名内存区域,将合适的4KB页自动合并为2MB的大页。
相关配置文件目录如下:
/sys/kernel/mm/transparent_hugepage/khugepaged/
关键配置文件:
0:关闭khugepaged主动整理内存碎片功能。
alloc_sleep_millisecs:重试间隔(单位:毫秒),当分配大页失败时,khugepaged下一次尝试分配前的等待时间,默认值为60000。
pages_to_scan:扫描页数,khugepaged每次唤醒后扫描的页数,默认值为4096。
scan_sleep_millisecs:扫描间隔(单位:毫秒),用于调节后台扫描频率,默认值为10000。
说明:如业务对延迟敏感,可适当加大扫描间隔,或关闭khugepaged整理功能。
3. 常见场景与调优建议
3.1 推荐配置:通用业务场景
开启madvise模式,仅在需要时才使用大页:
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
内存整理使用defer+madvise,后台合并且仅针对显式请求:
echo defer+madvise > /sys/kernel/mm/transparent_hugepage/defrag
3.2 数据库或延迟敏感服务
数据库如MySQL、PostgreSQL、Redis对性能抖动敏感,建议关闭THP:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
如需永久关闭,可在启动参数中加入:
sudo grubby --args="transparent_hugepage=never" --update-kernel="/boot/vmlinuz-$(uname -r)"
sudo reboot
3.3 控制khugepaged活跃度
如果系统中khugepaged守护进程的CPU使用率较高时,可以考虑以下配置降低khugepaged守护进程活跃度。
降低khugepaged扫描频率:
echo 30000 > /sys/kernel/mm/transparent_hugepage/khugepaged/scan_sleep_millisecs
增加分配失败后的重试间隔:
echo 120000 > /sys/kernel/mm/transparent_hugepage/khugepaged/alloc_sleep_millisecs
减少每次扫描页数:
echo 2048 > /sys/kernel/mm/transparent_hugepage/khugepaged/pages_to_scan
禁用khugepaged自动整理功能(如确实需要):
echo 0 > /sys/kernel/mm/transparent_hugepage/khugepaged/defrag
4. 查看THP的使用情况
查看THP全局使用情况:
cat /proc/meminfo | grep AnonHugePages
返回值为非零表示系统当前存在透明大页使用。
查看特定进程是否使用THP:
cat /proc/<PID>/smaps | grep AnonHugePages
将<PID>替换为实际进程号,可查看该进程哪些内存段正在使用大页。
5. THP与内存膨胀说明
正常情况下,Linux内存页大小是4KB。开启THP后,内核会尝试把多个4KB页合并成2MB的大页,这样可以减少TLB miss,提高性能。在小对象场景下开启THP可能会出现内存膨胀(内部碎片),并增加OOM风险。
(1)内部碎片
一个2MB的大页如果只用了很小一部分,其余空间仍然被进程占用,不能给其他进程使用。
比如:
- 普通小页:申请8KB → 用两个4KB页 → 基本无浪费。
- THP:申请8KB → 内核分配一个2MB大页 → 实际只用8KB,剩下~2MB全算"已用"。
(2)分配粒度变大
THP以2MB为单位分配,容易让内存占用迅速膨胀。
(3)内存回收不及时
THP的回收和迁移比4KB页更复杂,有时候会导致不能及时回收,从而表现为内存一直上涨。