本文主要介绍如何在Linux操作系统的实例中配置透明大页内存。
Transparent Huge Pages (THP)是一种 Linux 内存管理系统,它通过使用更大的内存页面来减少在具有大量内存的机器上进行转换后备缓冲区 (TLB) 查找的开销。
通过THP可以减少TLB miss和缺页中断,可以提升性能。例如:
应用程序需要2MB的内存,如果操作系统以4KB作为分页的单位,则需要512个页面,进而在TLB中需要512个表项,同时也需要512个页表项,操作系统需要经历至少512次TLB Miss和512次缺页中断才能将2MB应用程序空间全部映射到物理内存。
而当操作系统采用2MB作为分页的基本单位时,只需要1次TLB Miss和1次缺页中断,就可以为该应用程序空间建立虚拟映射,并在运行过程中无需再经历TLB Miss和缺页中断(假设未发生TLB项替换和 Swap)。
内部碎片。例如给需要1个字节数据的应用程序分配了2MB的大页内存,会导致出现内部碎片。
缺页处理延迟增高。尽管透明大页减少了缺页的次数,但更大的页面需要更长的时间从磁盘传输,从而导致缺页处理延迟增高。同时,清零大页也需要更长的时间。
内存路径加锁带来的访存性能下降。在khugepaged扫描进程内存,并将4kB页面合并为大页的这个过程中,对于操作的内存的各种分配活动都需要各种内存锁,直接影响程序的内存访问性能。并且,这个过程对于应用是透明的,在应用层面不可控制,对于专门为4kB内存页优化的程序来说,可能会造成随机的性能下降现象。
后台任务占用系统资源。当系统没有足够的连续内存时,会触发内存压缩和内存回收,导致系统性能下降。
透明大页对系统性能的影响需要分场景看待,您可以根据实际场景选择是否启用THP。
在如标准性能评估组织的 (Standard Performance Evaluation Corporation,简称SPEC) 的Java服务器性能测试(JAVA server Business Benchmark,简称SPECjbb)场景,应用程序需要使用大量内存,使用更大的page粒度映射内存以增加TLB中的命中率是有意义的,对于内存密集型工作负载,启用THP可能会产生可观的性能收益。
由于数据库往往具有稀疏而不是连续的内存访问模式,因此在启用THP的情况下,其工作负载通常表现不佳。例如在Linux上运行MongoDB时,应禁用THP以获得最佳性能。
查看透明大页功能状态。
执行如下命令,查看功能状态。
cat /sys/kernel/mm/transparent_hugepage/enabled
示例如下:
返回值说明:
[always] madvise never
:表示已启用透明大页。always [madvise] never
:只能通过madvise()
系统调用在MADV_HUGEPAGE
的内存区域使用透明大页。always madvise [never]
:表示已禁用透明大页。配置透明大页模式。
执行如下命令,启用透明大页。
echo always > /sys/kernel/mm/transparent_hugepage/enabled
执行如下命令,禁用透明大页。
echo never > /sys/kernel/mm/transparent_hugepage/enabled
执行如下命令,指定只能通过madvise()
系统调用在MADV_HUGEPAGE
的内存区域使用透明大页。
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
除此之外,您还可以在内核参数行中添加透明大页参数,实现在内核引导期间完成相关配置。
使用VNC连接实例,操作详情可查看通过控制台登录Linux实例。
当系统启动至内核选择界面时,按↑
或↓
键选择目标内核。
按e
键进入修改Grub引导文件页面。
将光标定位至Linux内核参数行,添加transparent_hugepage=always
、transparent_hugepage=madvise
或transparent_hugepage=never
参数,如下图所示。
按Ctrl
+ x
键完成配置。
进入操作系统后,可执行步骤2命令查看配置是否生效。
执行如下命令,查看系统级别的透明大页使用情况。
cat /proc/meminfo | grep AnonHugePages
示例如下:
AnonHugePages: 819200 kB
执行如下命令,查看进程级别的透明大页使用情况。
请将
[pid]
替换为目标进程的进程号。
cat /proc/[pid]/smaps | grep AnonHugePages
示例如下:
AnonHugePages: 0 kB AnonHugePages: 0 kB AnonHugePages: 0 kB AnonHugePages: 0 kB AnonHugePages: 0 kB
您可以通过如下方式配置透明大页碎片整理功能,当无法分配透明大页时,系统将自动完成相应操作整理大页碎片。
执行如下命令完成配置。
当无法分配透明大页时,暂停分配透明大页,并直接回收页面和压缩内存以立即分配透明大页。
echo always >/sys/kernel/mm/transparent_hugepage/defrag
执行如下命令完成配置。
当无法分配透明大页时,转而分配4kB普通页,同时在后台唤醒kswapd
以回收页面并唤醒kcompactd
以压缩内存,以便khugepaged
在连续内存可用的时候合成透明大页。
echo defer >/sys/kernel/mm/transparent_hugepage/defrag
执行如下命令完成配置。
当无法分配透明大页时,仅对通过madvise()
系统调用在MADV_HUGEPAGE
的内存区域分配透明大页的采用always
方式,其他区域分配4kB普通页。
echo madvise >/sys/kernel/mm/transparent_hugepage/defrag
执行如下命令完成配置。
当无法分配透明大页时,对于通过madvise()
系统调用在MADV_HUGEPAGE的内存区域分配透明大页的采用always
方式,其他区域采用defer
方式。
echo defer+madvise >/sys/kernel/mm/transparent_hugepage/defrag
您还可以执行如下命令,禁止碎片整理。
echo never >/sys/kernel/mm/transparent_hugepage/defrag
khugepaged是透明大页的守护进程,它的主要功能是定时唤醒,根据配置尝试将4k的普通page转成2M等大页,减少TLB压力,提高内存使用效率。但khugepaged在处理过程中需要使用各种内存锁,在一定程度上会影响系统性能。您可以根据实际需求配置khugepaged。
执行如下命令,禁用khugepaged碎片整理。
echo 0 > /sys/kernel/mm/transparent_hugepage/khugepaged/defrag
执行如下命令,启用khugepaged碎片整理。
echo 1 >/sys/kernel/mm/transparent_hugepage/khugepaged/defrag
执行如下命令,设置khugepaged每次扫描4096页(默认也是4096页)。
echo 4096 > /sys/kernel/mm/transparent_hugepage/khugepaged/pages_to_scan
执行如下命令,设置khugepaged每次唤醒的时间间隔为10000ms(默认也是10000ms)。
echo 10000 > /sys/kernel/mm/transparent_hugepage/khugepaged/scan_sleep_millisecs
执行如下命令,设置khugepaged分配大页失败后的等待时间为60000ms,防止短时间重复失败(默认也是60000ms)。
echo 60000 > /sys/kernel/mm/transparent_hugepage/khugepaged/alloc_sleep_millisecs
如果系统出现严重卡顿并且khugepaged使用率高达100%,您可以执行如下命令,禁用khugepaged。
echo 0 > /sys/kernel/mm/transparent_hugepage/khugepaged/defrag