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,您將看到內核輸出關于內存不足的日志信息,包括可能被殺死的進程詳情。