THP(Transparent Huge Page)reclaim功能用于解决因透明大页THP带来的内存问题(例如OOM)。本文介绍实现THP reclaim功能的接口,以及接口的示例操作说明。
背景信息
Linux操作系统的内存采用分页管理模式,其中的THP是指内核中2 MiB或1 GiB大小的大页面(普通的小页面大小为4 KiB),一般被称为透明大页。基于应用程序使用到的内存范围越来越大,地址转换产生的开销变得不可忽视。因此,当服务器上的应用程序申请内存时,内核会根据进程的实际情况动态分配透明大页,透明大页可以减少TLB(Translation Lookaside Buffer) Miss的出现概率,从而提升应用程序的性能。
THP在带来性能提升的同时,也产生了一定副作用,即可能产生Memory bloating(内存膨胀)问题。该问题产生的原因说明:透明大页申请释放的粒度为2 MiB(即512个小页面),相较于小页面,透明大页更容易产生内存碎片,进而导致内核分配的内存容量大于实际需要的内存容量。
Memory bloating可能引发OOM(Out Of Memory)。例如,一个应用程序实际需要使用2个小页面,即8 KiB内存,但是内核分配了1个透明大页。此时,除去应用程序实际需要的内存(2个小页面),透明大页剩下的内存(510个小页面)大小均为0。最终可能会因RSS(Resident Set Size)内存用量增加而导致OOM。
为解决THP可能引发的内存问题。Alibaba Cloud Linux增加了memcg粒度的THP reclaim功能。在内核回收内存时,该功能会把透明大页拆分为小页面,并将其中的全零页面(zero subpage)回收,从而避免内存的快速膨胀引发OOM。但您需要注意,由于THP reclaim功能会将透明大页拆分为小页面,所以相较于2 MiB大小的透明大页,THP reclaim功能会在一定程度上造成内存性能的回退。
接口说明
实现THP reclaim功能的接口说明,如下表所述:
接口 | 说明 |
| 开启或关闭THP reclaim功能。支持以下配置项:
THP reclaim功能默认为关闭状态,即接口默认值为disable。 |
| 查看THP reclaim功能当前的状态。接口内的参数说明如下:
该接口的参数值按照NUMA node的顺序(node0、node1)从左到右排列。 |
| 控制THP reclaim功能的触发机制。目前支持以下配置项:
|
| THP reclaim功能的全局配置接口。支持以下配置项:
|
功能限制
仅以下内核版本的Alibaba Cloud Linux镜像支持配置THP reclaim功能:
Alibaba Cloud Linux 2:
4.19.91-24.al7
及以上内核版本。Alibaba Cloud Linux 3:
5.10.134-15.al8
及以上内核版本。
您可以通过uname -r
命令查询镜像的内核版本。
配置THP reclaim功能
本示例操作中,将以创建一个名为test的memory cgroup为例介绍如何配置THP reclaim。
运行以下命令,创建一个名为test的memory cgroup。
sudo mkdir /sys/fs/cgroup/memory/test/
运行以下命令,开启test的THP reclaim功能。
sudo sh -c 'echo reclaim > /sys/fs/cgroup/memory/test/memory.thp_reclaim'
运行以下命令,确认test的THP reclaim功能成功开启。
cat /sys/fs/cgroup/memory/test/memory.thp_reclaim
返回结果如下图所示,被
[]
包裹的配置项为生效配置项,[reclaim]
表示test的THP reclaim功能已开启。运行以下命令,通过THP reclaim功能的全局配置接口强制开启THP reclaim功能。
sudo sh -c 'echo reclaim > /sys/kernel/mm/transparent_hugepage/reclaim'
如果您想强制关闭THP reclaim功能,可运行以下命令:
sudo sh -c 'echo disable > /sys/kernel/mm/transparent_hugepage/reclaim'
说明THP reclaim功能的全局配置接口
/sys/kernel/mm/transparent_hugepage/reclaim
在设置为强制开启(reclaim
)或强制关闭(disable
)时,接口生效的优先级会高于各个memory cgroup中的memory.thp_reclaim
接口,但不会影响各个memory cgroup中memory.thp_reclaim
接口的配置。运行以下命令,配置test的
memory.thp_reclaim_ctrl
接口的threshold
配置项。sudo sh -c 'echo "threshold 32" > /sys/fs/cgroup/memory/test/memory.thp_reclaim_ctrl'
该示例命令表示如果透明大页中的全零页面数量超过32,则会触发THP reclaim的全零页面回收功能。
主动触发THP reclaim的全零页面回收功能。
主动触发后,THP reclaim会把所有超过
threshold
配置的全零页面回收。配置项reclaim
存在以下配置方式:说明该配置项的调用方式为同步调用,并且为只写配置项,即您只能向
memory.thp_reclaim_ctrl
接口写入reclaim
以主动触发THP reclaim的全零页面回收功能,但不能通过cat命令查看到reclaim
配置项。运行以下命令,会主动触发当前memory cgroup的THP reclaim的全零页面回收功能。
sudo sh -c 'echo "reclaim 1" > /sys/fs/cgroup/memory/test/memory.thp_reclaim_ctrl'
运行以下命令,会主动递归触发当前memory cgroup以及该cgroup下所有子cgroup的THP reclaim的全零页面回收功能。
sudo sh -c 'echo "reclaim 2" > /sys/fs/cgroup/memory/test/memory.thp_reclaim_ctrl'
除了通过
reclaim
主动触发THP reclaim的全零页面回收功能。THP reclaim还会伴随内存回收而触发:内存出现OOM时,会触发THP reclaim的全零页面回收功能。
当memory cgroup触发memory后台异步回收时,会触发THP reclaim的全零页面回收功能。关于memory后台异步回收的更多信息,请参见Memcg后台异步回收。
运行以下命令,查看test的THP reclaim功能状态。
cat /sys/fs/cgroup/memory/test/memory.thp_reclaim_stat
返回结果示例如下:
queue_length 14 split_hugepage 523 reclaim_subpage 256207
该结果表示:
queue_length
表示THP reclaim管理的透明大页数量为14。split_hugepage
表示累计拆分的透明大页数量为523。reclaim_subpage
表示累计回收的全零页面数量为256207。
测试THP reclaim功能效果
本节基于C语言提供了进程申请透明大页的代码测试样例。您可以通过以下测试样例,查看到THP reclaim功能在开启与关闭时的区别。
运行以下命令,为内存使用量限制接口
memory.limit_in_bytes
设置1 GiB的限制。sudo sh -c 'echo 1G > /sys/fs/cgroup/memory/test/memory.limit_in_bytes'
设置后,您可以运行以下命令查看
memory.limit_in_bytes
接口的值。cat /sys/fs/cgroup/memory/test/memory.limit_in_bytes
查看结果如下图所示:
运行以下命令,关闭memcg后台异步回收功能。
关于memcg后台异步回收的更多信息,请参见Memcg后台异步回收。
sudo sh -c 'echo 0 > /sys/fs/cgroup/memory/test/memory.wmark_ratio'
分别在开启或关闭THP reclaim功能的前提下,运行以下命令对C语言代码进行测试,并查看测试结果。
gcc -o test <test.c>
其中,
<test.c>
的代码示例如下,您可以根据实际需求替换。// 申请1 G内存(即512个透明大页),其中10个透明大页包含部分全零页面。 #include <stdlib.h> // For posix_memalign #include <string.h> // For memset #include <unistd.h> // For pause #define HUGEPAGE_SIZE 4096 * 512 int main() { int i, thp = 512; char *addr; posix_memalign((void **)&addr, HUGEPAGE_SIZE, HUGEPAGE_SIZE * thp); for (i = 0; i < 10; i++) { memset(addr, 0xc, HUGEPAGE_SIZE >> 1); addr += HUGEPAGE_SIZE; } for (; i < thp; i++) { memset(addr, 0xc, HUGEPAGE_SIZE); addr += HUGEPAGE_SIZE; } pause(); return 0; }
在测试过程中,您可以在另一台终端通过
dmesg -wH
命令同步监控系统是否发生OOM事件和内存使用情况。测试结果根据THP reclaim功能的开启状态有所不同:THP reclaim功能开启:进程申请透明大页过程中,THP reclaim会把前序申请的透明大页拆分为小页,并回收其中的全零页面,从而减少内存的使用量,最终不会发生OOM。
THP reclaim功能关闭:系统不会主动拆分和回收全零页面,最终发生OOM,您将看到内核输出关于内存不足的日志信息,包括可能被杀死的进程详情。