为 openGauss 配置大页内存
openGauss 支持使用标准大页来分配共享内存,以提高数据库性能。
- 减少页表内存占用
- 减少页表维护开销
- 提高快表(TLB)命中率
- 减少缺页中断次数
环境
aarch64
- openEuler 22.03 LTS-SP4
查询大页配置与状态
标准大页与普通内存是独立开的,预留的大页会占用内存容量。
比如扩大大页池容量(增加大页预留数量)之后,可通过 free
命令观察到可用内存的减少。
# 查询系统支持的大页大小
ls /sys/kernel/mm/hugepages
# 查询当前大页大小、预留数与分配数
cat /proc/meminfo | grep Huge
# 查询内存使用情况
free -h
# 查询 NUMA 各节点大页预留数与分配数
cat /sys/devices/system/node/node*/meminfo | grep Huge
# 查询 NUMA 各节点内存使用情况
numactl -H
配置大页池容量
大页池与普通内存池的机制类似:
- 大页池最初预留的空闲大页数量与容量相等。
- 所有的空闲大页用自由表维护
- 从自由表中取出空闲大页分配给上层应用
- 上层应用释放大页
- 如果大页总数超过大页池容量,被释放的大页会恢复为普通内存
- 如果大页总数不超过大页池容量,被释放的大页会被塞回自由表
# 查询大页池容量
cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# 配置大页池容量
echo <huge-page-cnt> > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# 查询单个 NUMA 节点大页池容量
cat /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
# 为单个 NUMA 节点配置大页池容量
echo <huge-page-cnt> > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
修改大页大小
需要修改 GRUB 配置并重启。
修改 /etc/default/grub
文件,找到 GRUB_CMDLINE_LINUX
,在里面添加参数以指定大页大小,比如:
GRUB_CMDLINE_LINUX="... default_hugepagesz=2M hugepagesz=2M"
我们还可以在这里直接指定大页池容量,就不需要每次重启后手动配置了,比如:
GRUB_CMDLINE_LINUX="... default_hugepagesz=2M hugepagesz=2M hugepages=512"
通过文件 /sys/firmware/efi
确认启动模式:
[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS
依据启动模式将 /etc/default/grub
生成到对应的 grub.cfg
中:
# BIOS
grub2-mkconfig -o /boot/grub2/grub.cfg
# UEFI
grub2-mkconfig -o /boot/efi/EFI/openEuler/grub.cfg
于是直接重启:
reboot
重启后可以检查一下 GRUB 配置是否生效:
cat /proc/cmdline
允许用户组分配大页
# 查询允许分配大页的用户组 ID
sysctl -n vm.hugetlb_shm_group
# 查询用户组 ID
id -g <group-name>
# 配置允许分配大页的用户组 ID
sysctl -w vm.hugetlb_shm_group=<group-id>
启用 openGauss 大页功能
修改 postgresql.conf
:
# 启用大页
enable_huge_pages = on
# 使用系统默认的大页大小
huge_page_size = 0
或者直接:
gs_guc set -D ${PGDATA} -c 'enable_huge_pages = on'
gs_guc set -D ${PGDATA} -c 'huge_page_size = 0'
需要重启数据库:
gs_ctl restart
注意,启用大页功能后,gaussdb
启动时会依据 GUC 参数 shared_buffers
指定的容量,尝试通过大页分配共享缓冲区,如果大页池容量不足会导致启动失败。
这时可以估算一下,扩大大页池容量就行。
关于透明大页
参考资料:
https://www.pingcap.com/blog/transparent-huge-pages-why-we-disable-it-for-databases/
上文介绍的标准大页需要单独管理,而透明大页可以在上层应用不感知的情况下使用大页分配内存。 在大部分情况下可以实现与标准大页类似的效果,在访问连续内存的场景下减少与页表相关的开销,从而获得更好的性能。 但透明大页需要将普通页合并为大页,会使得系统内核更频繁地触发内存回收与内存压缩,这会增加额外的开销。
-
内存回收(memory reclaim)
释放掉不必要的内存,涉及 I/O。 典型的场景有:将虚拟内存写回交换分区,随后将其释放;将映射文件的内存写回存储设备(仅脏页),随后释放。
-
内存压缩(memory compaction)
碎片整理,移动被占用的零碎页以获得足够大的连续空闲内存。
而数据库应用访问的内存是比较稀疏的,从大页获得的性能提升较少,于是透明大页带来的开销就变得无法接受了。 开启透明大页导致数据库性能问题时,通常会看到更高的 CPU 占用率。
查询当前透明大页配置:
# 控制透明大页是否开启
cat /sys/kernel/mm/transparent_hugepage/enabled
# 该参数用于控制内核是否更积极地执行内存压缩,便于在需要时提供更多的大页
cat /sys/kernel/mm/transparent_hugepage/defrag
关闭透明大页相关特性:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag