About HugePages

简介

HugePages 是 Linux 内核的一个特性,它允许更大的页面管理内存,以替代 4KB 的页面大小。

操作系统把逻辑地址映射成物理地址时,需要把映射关系也存储到一块内存中,这部分内容就是页表(PageTables)。计算机内存是通过表映射(页表)的方式进行内存寻址。CPU 拥有内置的内存管理单元,包含这些页面的列表,每个页面通过页表条目引用。当内存越来越大的时候, CPU 需要管理这些内存页的成本也就越高,这样会对操作系统的性能产生影响。 在 64 位机器上,目前系统默认内存以 4KB 为一个页,作为内存寻址的最小单元,随着内存和进程数的不断增大,页表的大小将会不断增大。内存是以块即页的方式进行管理的,当前大部分系统默认的页大小为 4096 bytes 即 4K 。 1MB 内存等于 256 页; 1GB 内存等于 256000 页。

~]# getconf PAGESIZE
4096

在 Linux 操作系统中,即使是同一块共享内存,每个进程中的逻辑地址也是不相同的,因此不同进程中的映射表项也不相同。在 64 位的机器上,每个 4k 页需要占用大约 8 字节的内存,一台 48GB 内存的机器,如果分配了 24GB 的共享内存,则每个进程的页表大小为 24GB/4K*8=48MB;如果连接上 500 个进程,那么页表的大小将是 500*48MB=24GB。这会立刻把机器上的所有内存吃光。当然,并不是每个新连接一连接上来就会分配 48MB,而是当进程需要建立逻辑地址和物理地址之间的映射关系时才会分配,所以,进程占用的页表空间是缓慢增加的,但最终还是会占用很大的页表内存。 页表是必须装在内存的,而且是在 CPU 内存,太大就会发生大量 miss,内存寻址性能就会下降。
要查看是否存在大页表的问题,可以使用如下的命令来检查页表的大小:

~]# grep PageTables /proc/meminfo
PageTables: 82588 kB

如果发现页表的大小不是几十兆,而是达到了 1GB 以上,就说明共享内存使用存在此问题。基于共享内存的多进程架构的程序都会存在此问题。
Huge Page 就是为了解决这个问题,它使用 2MB 的大页代替传统小页 4KB 来管理内存,这样页表大小就可以控制的很小,进而全部装在 CPU 内存,防止出现 miss。

在 Linux 中,大页分为两种:一是静态大页面(Static Huge Pages,SHP)也称为标准大页,二是透明大页面(Transparent Huge Pages,THP)。从它们的名字就可以看出,SHP 是静态的,而 THP 是动态的。由于 THP 是在运行期做分配和管理,因此会有一定程度的延迟,对于内存密集型的应用(例如数据库类)十分不利,必须关闭它。

Static HugePages(标准大页)

Huge pages 是从 Linux Kernel 2.6 后被引入的,目的是通过使用大页内存来取代传统的 4kb 内存页面,以适应越来越大的系统内存,让操作系统可以支持现代硬件架构的大页面容量功能。
Huge pages 有两种格式大小:2MB 和 1GB,2MB 页块大小适合用于 GB 大小的内存,1GB 页块大小适合用于 TB 级别的内存;2MB 是默认的页大小。

标准大页的页面大小:

~]# grep Hugepagesize /proc/meminfo
Hugepagesize: 2048 kB

使用 Huge Pages 优点

  • 适合大内存或内存密集型应用(例如数据库)的调优。
  • 减小页表尺寸(避免页表过大),降低查找缓存(TLB,Translation Lookaside Buffer) 的 cache-miss,加速 VM 内存转换。
  • 可以使花费在内存管理上的 CPU 时间更少,从而提高性能。

使用 Huge Pages 缺点

  • 开启该功能需要进行额外设置,不同的数据库配置方法不同。
  • 大页内存一旦设置,内存就实际分配出去了,也会一直驻留在内存中,不会被交换出去。若数据库没有使用这部分大页,那么相当于这部分大页内存是白白浪费掉的,因为它不会给文件系统缓存使用,也不能给其它不使用大页内存的程序使用。

Transparent HugePages(透明大页)

Transparent Huge Pages 缩写 THP,这个是 RHEL 6 开始引入的一个功能,只支持 2M 页块,在 Linux 6 上透明大页是默认启用的。
由于 Huge pages 很难手动管理,而且通常需要对代码进行重大的更改才能有效的使用,因此 RHEL 6 开始引入了 Transparent Huge Pages(THP),THP 是一个抽象层,能够自动创建、管理和使用传统大页。THP 为系统管理员和开发人员减少了很多使用传统大页的复杂性,因为 THP 的目标是改进性能,因此其它开发人员(来自社区和红帽)已在各种系统、配置、应用程序和负载中对 THP 进行了测试和优化。这样可让 THP 的默认设置改进大多数系统配置性能。但是,<font color=recommand> 不建议对数据库工作负载使用 THP (Oracle、MySQL、PostgreSQL、MongoDB 均建议关闭 THP)</font>,因为 THP 在运行时动态分配内存,而运行时的内存分配会有延迟,对于数据库的管理来说并不友好,会导致数据库性能抖动。

如何关闭 THP?(禁用透明大页)

检查当前的 transparent_hugepage 状态

~]# cat /sys/kernel/mm/transparent_hugepage/enabled
always [madvise] never

never - 关闭,不使用透明大页内存
always - 尽量使用透明内存,扫描内存,有 512 个 4k 页面可以整合,就整合成一个 2M 的页面
madvise - 避免改变内存占用,表示只在 MADV_HUGEPAGE 标志的 VMA 中使用 THP

运行时关闭:

echo never > /sys/kernel/mm/transparent_hugepage/enabled

启动时关闭:

GRUB 配置文件备份

cp /etc/default/grub /etc/default/grub.`date +%F`.bak
cp /boot/grub2/grub.cfg /boot/grub2/grub.cfg.`date +%F`.bak

编辑 /etc/default/grub 文件,在 GRUB_CMDLINE_LINUX 那一行后面追加 transparent_hugepage=never

~]# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="rd.lvm.lv=ol/root rd.lvm.lv=ol/swap rhgb quiet numa=off transparent_hugepage=never"
GRUB_DISABLE_RECOVERY="true"

使用 grub2-mkconfig 重新生成 grub.cfg 配置文件

~]# grub2-mkconfig -o /boot/grub2/grub.cfg
~]# reboot

重启后状态确认

~]# cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.10.0-1127.el7.x86_64 root=/dev/mapper/rhel-root ro crashkernel=auto rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rd.lvm.lv=rhel/usr rhgb quiet transparent_hugepage=never

~]# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]

如果未成功关闭,可能是由于 tunedktune 造成的,请参考以下 KB

Disabling transparent hugepages (THP) on Red Hat Enterprise Linux 6 is not taking effect
Disable Transparent Huge Pages(THP) persistently not working on RHEL7