Linux 内存巨页与透明巨页学习

1. linux 内存管理单元介绍

Linux 系统管理内存的最小单元为页,默认页大小为 4KB,可通过 getconf PAGESIZE 查看。

程序访问的是虚拟内存,虚拟地址与物理地址的转换关系记录在页表(Page Table)中。

当 CPU 访问虚拟地址时,会优先查询 TLB(地址转换旁路缓冲存储器),TLB 缓存了常用的虚拟地址→物理地址映射。

如果 TLB 中没有找到(TLB Miss),CPU 会去内存中查询页表,并把新的映射关系缓存到 TLB。

但 TLB 容量很小,能缓存的页表映射条目有限。如果申请内存较大,对应的内存页数量就会非常多,导致 TLB 频繁失效。

这时 CPU 就需要频繁访问内存中的页表查找地址映射,CPU 负载随之升高。

为了降低CPU的负载,就可以通过巨页来增大内存页的大小,通过TLB就能更快的访问到物理内存。

查看系统默认的页大小:

2. 巨页介绍

linux 巨页技术有两个:

  • Huge Pages(静态巨页):

    静态巨页,就是系统启动时就预先分配好、数量固定、位置固定、不会被内核动的大页内存。

    通过大幅减少页表数量、提高 TLB 命中率,显著降低 CPU 地址翻译负担。

  • Transparent Huge Pages (透明巨页)

    THP 透明巨页是内核自动把 4KB 页合并成 2MB 巨页的机制,合并时会卡顿,对应用透明。

    优点是自动优化、无需配置;

    缺点是会造成内存紧缩、CPU 毛刺、IO 波动。

查看是否开启巨页:

查看是否开启透明巨页:

cat /sys/kernel/mm/transparent_hugepage/enabled

csharp 复制代码
[always] madvise never		# 当前状态是开启的
  • always:完全开启状态
  • madvise:只有程序显式要求时才用巨页
  • never: 完全关闭透明巨页

查看是否开启静态巨页:

grep -i huge /proc/meminfo | grep HugePages_Total

csharp 复制代码
HugePages_Total:       0

0 代表未开启,大于0等于分配了多少巨页

开启两种巨页的方式:

开启静态巨页:

复制代码
# 临时开启:
echo 256 > /proc/sys/vm/nr_hugepages   	# 提前分配256个2MB的巨页
# 永久开启:
echo "vm.nr_hugepages=256"  >>/etc/sysctl.conf
sysctl -p		# 立即生效
csharp 复制代码
[root@localhost ~]# cat /proc/meminfo | grep -E 'MemFree|Hugepagesize|HugePages_Total'
MemFree:         1481000 kB				# 未开启巨页前当前剩余内存量
HugePages_Total:       0					# 未开启巨页前巨页数量
Hugepagesize:       2048 kB				# 默认巨页大小
[root@localhost ~]# echo 256 > /proc/sys/vm/nr_hugepages        # 提前分配256个2MB的巨页
[root@localhost ~]# cat /proc/meminfo | grep -E 'MemFree|Hugepagesize|HugePages_Total'
MemFree:          955456 kB			# 开启巨页后的内存剩余量已经减少了
HugePages_Total:     256				# 当前巨页数量
Hugepagesize:       2048 kB			

开启透明巨页:

复制代码
# 临时开启
echo always > /sys/kernel/mm/transparent_hugepage/enabled				# 开启透明巨页
echo always > /sys/kernel/mm/transparent_hugepage/defrag				# 开启透明巨页的内存碎片整理
# 永久开启
cat > /etc/systemd/system/enable-transparent-huge-pages.service <<EOF
[Unit]
Description=Enable Transparent Hugepages (THP)
DefaultDependencies=no
After=sysinit.target local-fs.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo always | tee /sys/kernel/mm/transparent_hugepage/enabled > /dev/null && echo always | tee /sys/kernel/mm/transparent_hugepage/defrag > /dev/null'

[Install]
WantedBy=basic.target
EOF
systemctl daemon-reload
# 或者兼容老的系统
cat >> /etc/rc.local <<EOF
echo always > /sys/kernel/mm/transparent_hugepage/enabled
echo always > /sys/kernel/mm/transparent_hugepage/defrag
EOF
chmod +x /etc/rc.local

可以看出系统初始被被内核自动合并为 2MB 巨页的内存为4096 kB,后面执行stress-ng 压测后,被自动合并的内存页明显上升了。

关闭透明巨页:

复制代码
# 临时关闭透明巨页
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
# 永久关闭,如果之前有设置开启的service文件,记得disable掉
cat > /etc/systemd/system/disable-transparent-huge-pages.service <<EOF
[Unit]
Description=Disable Transparent Hugepages (THP)
DefaultDependencies=no
After=sysinit.target local-fs.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled && echo never > /sys/kernel/mm/transparent_hugepage/defrag'

[Install]
WantedBy=basic.target
EOF
systemctl daemon-reload

关闭静态巨页:

复制代码
# 临时关闭:
echo 0 > /proc/sys/vm/nr_hugepages   	# 提前分配256个2MB的巨页
# 永久关闭:
echo "vm.nr_hugepages=0"  >>/etc/sysctl.conf
sysctl -p		# 立即生效

3. 透明巨页和静态巨页的使用场景

  • 透明巨页

    内核自动合并内存,在合并的时候会有卡顿,不适合高IO场景,对延时敏感,不能接受突然卡顿几毫秒~几十毫秒。

    适合对延时不敏感的业务比如:文件服务器,云盘 / 对象存储类服务,日志收集、备份服务器。

  • 静态巨页 HugePages

    内核一次性分配,提前占用内存,不适合小内存服务器,一次性分配内存很小的程序。

    适合申请内存比较多的业务且不经常回收: 虚拟机、redis、mysql。

参考文章:

https://www.jianshu.com/p/391f42f8fb0d

https://mp.weixin.qq.com/s/1CLV53M-1-pomC5Zsnu_dw

https://www.mongodb.com/zh-cn/docs/manual/tutorial/disable-transparent-huge-pages/

https://blog.csdn.net/TiDB_PingCAP/article/details/109227464

https://docs.redhat.com/en/documentation/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/s-memory-transhuge.html

相关推荐
不羁的木木5 分钟前
ArkWeb实战学习笔记04-JavaScript与Native通信
笔记·学习·harmonyos
andlbds6 分钟前
解决Ubuntu20.04进入系统卡死在厂商Logo界面问题
linux·ubuntu
MIXLLRED10 分钟前
解决: Ubuntu 22.04上树莓派4B扩展板ROS2兼容性修复指南
linux·ubuntu·树莓派
zizle_lin13 分钟前
CentOS配置yum源
linux·运维·centos
weixin_4896900219 分钟前
【IDEA 2025.2.4】 Maven 仅能手动 Reload All Maven Projects 问题解决
java·maven·intellij-idea
雨辰AI19 分钟前
MySQL 迁移至达梦 DM9 完整改造指南|99% SQL 零改动
java·开发语言·数据库·sql·mysql·政务
golang学习记19 分钟前
Intellij IDEA 2026重磅更新!开发体验大升级
java·ide·intellij-idea
弹简特23 分钟前
【Java项目-轻聊】05-AI赋能设计接口文档
java·开发语言
li星野24 分钟前
RAG优化系列:HyDE(假设文档嵌入)——让LLM先写答案再检索
python·学习
知识分享小能手27 分钟前
Flask入门学习教程,从入门到精通,Flask智能租房——用户中心知识点详解(9)
python·学习·flask