跳转至

内存大页

HugePages 是一种内存管理技术,允许操作系统使用大页面(Huge Pages)而不是传统的小页面来提高内存访问效率和减少管理开销。它通常用于内存密集型的应用程序,如数据库、虚拟化、科学计算等,能够提高系统性能,减少内存分配和页面管理的开销。

1. 页面(Page)与大页面(Huge Page)

在计算机系统中,内存被划分为若干个固定大小的块,称为页面(Page)。传统的页面大小通常为 4 KB(在 x86 系统上)。当一个应用程序需要大量内存时,操作系统将分配很多这样的 4 KB 页面,并维护一个页面表来管理它们。

然而,当系统需要处理大量内存时,管理成千上万的 4 KB 页面会导致高昂的开销。为了提高性能,操作系统提供了大页面,通常是 2 MB1 GB(取决于硬件架构和配置)。

2. HugePages 的优势

使用 HugePages 可以带来多个性能优势,特别是对于内存密集型的应用:

1. 减少页表管理的开销

  • 每个页面(4 KB)需要操作系统维护一个页表条目(Page Table Entry,PTE)。对于大量小页面(如 4 KB),操作系统需要维护很多页表条目。
  • 大页面(如 2 MB 或 1 GB)则意味着操作系统只需要维护更少的页表条目,因为每个大页面管理的内存量更多。这大大减少了页表的管理开销,尤其是在处理大量内存时。

2. 减少 TLB(Translation Lookaside Buffer)缺失

  • TLB 是一种缓存机制,用于加速虚拟地址到物理地址的转换。使用大页面可以减少 TLB 缺失的次数,因为每个大页面内存块占用更少的 TLB 条目,从而提高内存访问速度。
  • 小页面由于较小,可能导致 TLB 缓存未命中,需要进行更多的页表查找。

3. 减少页面交换(Page Swapping)

  • 使用 HugePages 后,操作系统将更少的页面表条目插入交换空间中。由于大页面较少,页面交换时的开销也会减少,特别是在高负载的情况下。

4. 提高性能

  • 许多内存密集型应用(如数据库、虚拟机监控程序、科学计算应用等)可以通过使用 HugePages 获得显著的性能提升。减少页面管理和 TLB 缺失的次数可以使这些应用更高效地使用内存。

3. 如何启用 HugePages

HugePages 需要手动配置,通常有两种方式:静态分配动态分配

1. 静态 HugePages

静态 HugePages 是在系统启动时预留特定数量的大页面。系统启动时,这些页面会被保留并固定分配给应用程序,不能被其他进程使用。

  • 配置静态 HugePages:

  • 检查当前系统支持的页面大小(通常是 2 MB 或 1 GB):

    [root@ ~]# ll /sys/kernel/mm/hugepages/
    total 0
    drwxr-xr-x 2 root root 0 Feb 17 11:59 hugepages-1048576kB
    drwxr-xr-x 2 root root 0 Feb 17 11:59 hugepages-2048kB

    这表示系统支持 2 MB和1GB的大页面。

  • 可以手动 echo 个数到指定的/sys/下的文件中。这个如果是硬件设备,可以询问厂商支持什么样变更。

2. 动态 HugePages

动态 HugePages 是操作系统在运行时根据需要动态分配的,而不是预先分配给特定进程。这种方式比静态 HugePages 更灵活,但可能会导致性能不如静态分配。

在现代的 Linux 内核中,Transparent Huge Pages(THP)是自动启用的,它允许操作系统在后台自动处理页面的合并和拆分,使得应用程序能够透明地使用大页面而不需要修改代码。

  • 查看和启用 Transparent Huge Pages(THP)
cat /sys/kernel/mm/transparent_hugepage/enabled

输出示例:

always [madvise] never

如果需要启用 THP,可以将其设置为 alwaysmadvise

always 始终启用透明大页:内核会尝试自动将普通内存页(4KB)合并为透明大页(通常为2MB),无需应用主动请求。
madvise 按需启用:仅当应用程序通过 madvise() 系统调用显式请求时(如使用 MADV_HUGEPAGE 标志),内核才会为该应用分配透明大页。
never 完全禁用透明大页:内核不会自动合并内存页,也不会响应应用的透明大页请求。

更改大页支持

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

4. HugePages 的使用限制与缺点

尽管 HugePages 在内存管理上有许多优势,但也有一些潜在的限制和缺点:

  • 内存浪费:由于每个大页面的大小较大(例如 2 MB 或 1 GB),如果应用程序并不需要这么大的内存块,可能会浪费内存。
  • 无法动态回收:静态 HugePages 分配后,无法像普通页面一样灵活地回收和重新分配。这可能导致内存碎片化问题。
  • 对某些应用不适用:一些应用程序可能并不需要使用大页面,或者使用大页面并不会显著提升性能。

5. 检查 HugePages 使用情况

你可以使用以下命令来查看当前系统的 HugePages 使用情况:

  • 查看 HugePages 的总数和空闲数:
cat /proc/meminfo | grep -i -e 'Direct' -e 'huge'

输出示例:

AnonHugePages:         0 kB      # 【内核态】匿名透明大页(THP,2MB页)占用量,由内核自动管理,未被应用使用。
ShmemHugePages:        0 kB      # 【内核态】共享内存(如 tmpfs)使用的透明大页(2MB页),未使用。
HugePages_Total:       0         # 【用户态】全局传统大页(如 2MB)总数,未配置此类大页。
HugePages_Free:        0         # 【用户态】空闲的传统大页数量(2MB),因未配置故为 0。
HugePages_Rsvd:        0         # 【用户态】预留未分配的传统大页数量(2MB),未配置故为 0。
HugePages_Surp:        0         # 【用户态】超额分配的传统大页数量(2MB),未启用超额分配。
Hugepagesize:       2048 kB      # 【内核态】系统默认大页大小(2MB),仅反映内核参数,与用户配置的 1GB 大页无关。
Hugetlb:        507510784 kB     # 【用户态】所有大页类型(含 1GB)的预留内存总量,约 484GB(用户态显式预留)。
DirectMap4k:     1321496 kB      # 【内核态】内核用 4KB 页直接映射的物理内存,用于小内存区域。1.26 GB。
DirectMap2M:    15366144 kB      # 【内核态】内核用 2MB 页直接映射的物理内存,提升内核自身访问效率。14.65 GB。
DirectMap1G:    520093696 kB     # 【内核态】内核用 1GB 页直接映射的物理内存,反映连续物理内存区域。496 GB。

HugePages 是一种用于提高内存管理效率的技术,特别适用于内存密集型的应用程序。通过减少页表管理开销和提高 TLB 缓存命中率,HugePages 提高了内存访问的性能。它有静态和动态两种配置方式,静态配置适用于预先知道内存需求的应用,而动态配置通过 Transparent Huge Pages(THP)在后台自动进行内存优化。

参考文章:https://www.kernel.org/doc/html/latest/admin-guide/mm/hugetlbpage.html