Red Hat Training

A Red Hat training course is available for RHEL 8

第 33 章 配置巨页

物理内存在固定大小的块(称为页面)中进行管理。在 Red Hat Enterprise Linux 8 支持的 x86_64 构架中,内存页面的默认大小为 4 KB。此默认页面大小已证明适合通用操作系统,如支持多种不同工作负载的 Red Hat Enterprise Linux。

然而,在某些情况下,特定应用程序可能会因使用更大的页面大小而受益。例如:使用 4 KB 页面时,处理大量且相对固定的数百兆字节甚至几十兆字节的数据的应用程序可能会有性能问题。此类数据集可能需要大量 4 KB 页面,这可能会导致操作系统和 CPU 开销。

这部分提供有关 Red Hat Enterprise Linux 8 中的巨页以及如何配置它们的信息。

33.1. 可用的巨页功能

使用 Red Hat Enterprise Linux 8 时,您可以将巨页用于处理大数据集的应用程序,并改进此类应用程序的性能。

以下是 Red Hat Enterprise Linux 8 支持的巨页方法:

HugeTLB pages

HugeTLB 页面也称为静态巨页。保留 HugeTLB 页面的方法有两种:

Transparent HugePages (THP)

使用 THP 时,内核会自动为进程分配巨页,因此不需要手动保留静态大页面。以下是 THP 中的两种操作模式:

  • system-wide: 在这里,内核会尝试在可能分配大页面时为进程分配大页面,该进程正在使用很大的连续虚拟内存区域。
  • per-process: 在这里,内核只为您可以使用 madvise()系统调用指定的单独进程的内存区域分配巨页。

    注意

    THP 功能只支持 2 MB 页面。

    有关启用和禁用 THP 的详情,请参考 启用透明大页并禁用透明大页

33.2. 在引导时保留 HugeTLB 页面的参数

在引导时,使用以下参数来影响 HugeTLB 页面行为:

表 33.1. 用于在引导时配置 HugeTLB 页面的参数

参数描述默认值

hugepages

定义在启动时在内核中配置的持久大页面数量。

在 NUMA 系统中,定义了此参数的巨页在节点间平均分配。

您可以通过更改 /sys/devices/system/node/node_id/hugepages/hugepages-size/nr_hugepages 文件中的节点值,在运行时为特定节点分配巨页。

默认值为 0

要在引导时更新这个值,请在 /proc/sys/vm/nr_hugepages 文件中更改此参数的值。

hugepagesz

定义在启动时在内核中配置的持久大页面大小。

有效值为 2 MB1 GB。默认值为 2 MB

default_hugepagesz

定义在启动时在内核中配置的持久性巨页的默认大小。

有效值为 2 MB1 GB。默认值为 2 MB

33.3. 在引导时配置 HugeTLB

HugeTLB 子系统支持的页面大小取决于架构。x86_64 架构支持 2 MB 巨页和 1 GB 巨页。

这个步骤描述了如何在引导时保留 1 GB 页面。

流程

  1. 通过以 root 用户身份在 /etc/default/grub 文件中的内核命令行选项中附加以下行,为 1 GB 页面创建一个 HugeTLB 池:

    default_hugepagesz=1G hugepagesz=1G
  2. 使用编辑的默认文件重新生成 GRUB2 配置:

    1. 如果您的系统使用 BIOS 固件,请执行以下命令:

      # grub2-mkconfig -o /boot/grub2/grub.cfg
    2. 如果您的系统使用 UEFI 框架,请执行以下命令:

      # grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
  3. /usr/lib/systemd/system/ 目录中创建一个名为 hugetlb-gigantic-pages.service 的新文件并添加以下内容:

    [Unit]
    Description=HugeTLB Gigantic Pages Reservation
    DefaultDependencies=no
    Before=dev-hugepages.mount
    ConditionPathExists=/sys/devices/system/node
    ConditionKernelCommandLine=hugepagesz=1G
    
    [Service]
    Type=oneshot
    RemainAfterExit=yes
    ExecStart=/usr/lib/systemd/hugetlb-reserve-pages.sh
    
    [Install]
    WantedBy=sysinit.target
  4. /usr/lib/systemd/ 目录中创建一个名为 hugetlb-reserve-pages.sh 的新文件并添加以下内容:

    在添加以下内容时,将 number_of_pages 替换为您要保留的 1GB 页面数,并使用要保留这些页面的节点名称替换 node。

    #!/bin/sh
    
    nodes_path=/sys/devices/system/node/
    if [ ! -d $nodes_path ]; then
        echo "ERROR: $nodes_path does not exist"
        exit 1
    fi
    
    reserve_pages()
    {
        echo $1 > $nodes_path/$2/hugepages/hugepages-1048576kB/nr_hugepages
    }
    
    reserve_pages number_of_pages node

    例如:要在 node0 上保留两个 1 GB 页面,在 node 1 上保留 1 个 1GB 页面,将 number_of_pages 替换为 2 用于 node0,1 用于 node1

    reserve_pages 2 node0
    reserve_pages 1 node1
  5. 创建可执行脚本:

    # chmod +x /usr/lib/systemd/hugetlb-reserve-pages.sh
  6. 启用早期引导保留:

    # systemctl enable hugetlb-gigantic-pages
注意
  • 您可以通过随时写入 nr_hugepages,尝试在运行时保留更多 1GB 页面。但是,由于内存碎片,此类保留可能会失败。保留 1 GB 页面的最可靠方法是使用这个 hugetlb-reserve-pages.sh 脚本,该脚本会在引导过程早期运行。
  • 保留静态大页面可以有效地减少系统可用的内存量,并阻止它正确使用内存容量。虽然正确大小的保留大页面池对于使用大页面的应用程序很有用,但保留巨页池的大小过大或未使用的剩余大页面最终将阻碍整体系统性能。在设置保留的巨页池时,请确保系统可以正确利用其完整内存容量。

其它资源

  • systemd.service(5) man page
  • /usr/share/doc/kernel-doc-kernel_version/Documentation/vm/hugetlbpage.txt file

33.4. 在运行时保留 HugeTLB 页面的参数

在运行时,使用以下参数来影响 HugeTLB 页面行为。

表 33.2. 在运行时配置 HugeTLB 页面的参数

参数描述文件名

nr_hugepages

定义分配给指定 NUMA 节点的指定大小的巨页数量。

/sys/devices/system/node/node_id/hugepages/hugepages-size/nr_hugepages

nr_overcommit_hugepages

定义系统可以通过过量使用内存来创建和使用的额外巨页的最大数量。

将任何非零值写入该文件表示系统会从内核的普通页面池中获取巨页的数量(如果持久的大页面池已耗尽)。当这些大页面变得未使用后,它们会被释放并返回到内核的普通页面池。

/proc/sys/vm/nr_overcommit_hugepages

33.5. 在运行时配置 HugeTLB

这个步骤描述了如何向 node2 添加 2048 kB 巨页。

要根据您的要求保留页面,请替换:

  • 20 以及您要保留的巨页数量,
  • 2048KB,带有巨页大小,
  • node2 带有您要保留页面的节点。

流程

  1. 显示内存统计信息:

    # numastat -cm | egrep 'Node|Huge'
                     Node 0 Node 1 Node 2 Node 3  Total add
    AnonHugePages         0      2      0      8     10
    HugePages_Total       0      0      0      0      0
    HugePages_Free        0      0      0      0      0
    HugePages_Surp        0      0      0      0      0
  2. 将指定大小的巨页数量添加到节点:

    # echo 20 > /sys/devices/system/node/node2/hugepages/hugepages-2048kB/nr_hugepages

验证步骤

  • 确保添加了巨页数量:

    # numastat -cm | egrep 'Node|Huge'
                     Node 0 Node 1 Node 2 Node 3  Total
    AnonHugePages         0      2      0      8     10
    HugePages_Total       0      0     40      0     40
    HugePages_Free        0      0     40      0     40
    HugePages_Surp        0      0      0      0      0

其它资源

  • numastat(8) man page

33.6. 启用透明大页

在 Red Hat Enterprise Linux 8 中默认启用 THP。但是,您可以启用或禁用 THP。

这个步骤描述了如何启用 THP。

流程

  1. 检查 THP 的当前状态:

    # cat /sys/kernel/mm/transparent_hugepage/enabled
  2. 启用 THP:

    # echo always > /sys/kernel/mm/transparent_hugepage/enabled
  3. 要防止应用程序分配超过必要数量的内存资源,请禁用系统范围的透明巨页,并只为通过 madvise 明确请求它的应用程序启用它们:

    # echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
注意

有时,为短期的分配提供低延迟的优先级高于立即通过长期分配实现最佳性能。在这种情况下,您可以在启用 THP 的同时禁用直接紧凑。

直接紧凑是在巨页分配期间异步内存紧凑。禁用直接紧凑不保证保存内存,但可以降低频繁页面错误时出现较高延迟的风险。请注意,如果工作负载显著受益于 THP,性能会降低。禁用直接压缩:

# echo madvise > /sys/kernel/mm/transparent_hugepage/defrag

其它资源

33.7. 禁用透明大页

在 Red Hat Enterprise Linux 8 中默认启用 THP。但是,您可以启用或禁用 THP。

这个步骤描述了如何禁用 THP。

流程

  1. 检查 THP 的当前状态:

    # cat /sys/kernel/mm/transparent_hugepage/enabled
  2. 禁用 THP:

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

33.8. 对转换前缓冲大小的影响

从页表中读取地址映射非常耗时且耗费资源,因此 CPU 构建时会使用最近使用的地址的缓存,称为 Translation Lookaside Buffer(TLB)。但是,默认 TLB 只能缓存一定数量的地址映射。

如果请求的地址映射不在 TLB 中(称为 TLB miss),则系统仍需要读取页表以确定物理地址到虚拟地址映射。由于应用程序内存要求和用于缓存地址映射的页面大小之间的关系,具有大型内存要求的应用程序更有可能遭受 TLB 未命中性能下降的问题,而不是内存要求最低的应用程序。因此,尽可能避免 TLB 未命中非常重要。

HugeTLB 和 Transparent Huge Page 功能允许应用程序使用大于 4 KB 的页面。这允许 TLB 中存储的地址引用更多内存,这可减少 TLB 未命中并提高应用性能。