数据库

注册

 

发新话题 回复该主题

为什么HugePages可以提升数据 [复制链接]

1#

为什么这么设计(Why’sTHEDesign)是一系列关于计算机领域中程序设计决策的文章,我们在这个系列的每一篇文章中都会提出一个具体的问题并从不同的角度讨论这种设计的优缺点、对具体实现造成的影响。如果你有想要了解的问题,可以在文章下面留言。

内存是计算机的重要资源,虽然今天大多数的服务对内存的需求都没有那么高,但是数据库以及Hadoop全家桶这些服务却是消耗内存的大户,它们在生产环境动辄占用GB和TB量级的内存来提升计算的速度,Linux操作系统为了更好、更快地管理这些内存并降低开销引入了很多策略,我们今天要介绍的是HugePages,也就是大页[^1]。

绝大多数的CPU架构都支持更大的页面,只是不同操作系统会使用不同的术语,例如:Linux上的HugePages、BSD上的SuperPages以及Windows上的LargePages,这些不同的术语都代表着类似的大页面功能。

图1-CPU架构和更大的页面

我们都知道Linux会以页为单位管理内存,而默认的页面大小为4KB,虽然部分处理器会使用8KB、16KB后者64KB作为默认的页面大小,不过4KB仍然是操作系统的默认页面配置的主流[^2],虽然64KB的页面是4KB的16倍,但是与最小2MB的HugePages相比,64KB的页面实在是不够大,更不用说默认的4KB了:

图2-默认和大页面大小

2MB一般都是HugePages的默认大小,在arm64和x86_64的架构上甚至支持1GB的大页面,是Linux默认页面大小的,倍,我们可以使用如下所示的命令查看当前机器上HugePages的相关信息:

$cat/proc/meminfo

grepHugeAnonHugePages:kBShmemHugePages:0kBFileHugePages:0kBHugePages_Total:0HugePages_Free:0HugePages_Rsvd:0HugePages_Surp:0Hugepagesize:kBHugetlb:0kB

通过上面的输出结果,我们可以看到当前机器上的大页面默认大小为2MB并且大页面的数量也为0,即没有进程在申请或者使用大页。各位读者可以在Linux尝试执行上述命令,如果机器上没有做过额外的配置,那么使用上述命令得到的输出与这里也不会有太大的差别。

/proc/sys/vm/nr_hugepages中存储的数据就是大页面的数量,虽然在默认情况下它的值都是0,不过我们可以通过更改该文件的内容申请或者释放操作系统中的大页:

$echo1/proc/sys/vm/nr_hugepages$cat/proc/meminfo

grepHugePages_HugePages_Total:1HugePages_Free:1...

在Linux中,与其他内存的申请和释放方式相同,我们可以在向mmap系统调用中传入MAP_HUGETLB标记申请操作系统的大页并使用munmap释放内存[^3],使用如下所示的代码片段可以在操作系统中申请2MB的大页:

size_ts=(2UL**);char*m=mmap(NULL,s,PROT_READ

PROT_WRITE,MAP_PRIVATE

MAP_ANONYMOUS

MAP_HUGETLB/*flags*/,-1,0);munmap(m,s);

虽然HugePages的申请方式与默认的内存相差不多,但是它实际上是操作系统单独管理的特殊资源,Linux会在/proc/meminfo中单独展示HugePages的相关数据,而容器编排系统Kubernetes也会认为大页是不同于内存的独立资源,如下所示的Pod也需要单独申请大页资源[^4]:

apiVersion:v1kindodmetadata:namee-pages-examplespec:containers:-name:example...volumeMounts:-mountPath:/hugepages-2Minameepage-2mi-mountPath:/hugepages-1Ginameepage-1giresourcesmitsepages-2Mi:Mihugepages-1Gi:2Gimemory:Mirequests:memory:Mivolumes:-nameepage-2miemptyDir:medium:HugePages-2Mi-name:hugepage-1giemptyDir:medium:HugePages-1Gi

作为Linux从2.6.32引入的新特性,HugePages能够提升数据库、Hadoop全家桶等占用大量内存的服务的性能,该特性对于常见的Web服务以及后端服务没有太多的帮助,反而可能会影响服务的性能,我们在这篇文章中会介绍HugePages为什么能够提升数据库等服务的性能:

HugePages可以降低内存页面的管理开销;HugePages可以锁定内存,禁止操作系统的内存交换和释放;管理开销

虽然HugePages的开启大都需要开发或者运维工程师的额外配置,但是在应用程序中启用HugePages却可以在以下几个方面降低内存页面的管理开销:

更大的内存页能够减少内存中的页表层级,这不仅可以降低页表的内存占用,也能降低从虚拟内存到物理内存转换的性能损耗;更大的内存页意味着更高的缓存命中率,CPU有更高的几率可以直接在TLB(Translationlookasidebuffer)中获取对应的物理地址;更大的内存页可以减少获取大内存的次数,使用HugePages每次可以获取2MB的内存,是4KB的默认页效率的倍;

因为进程的地址空间都是虚拟的,所以CPU和操作系统需要记录页面和进程之间的对应关系,操作系统中的页面越多,我们也就需要花费更多的时间在如下所示的五层页表结构中查找虚拟内存对应的物理内存,我们会根据虚拟地址依次访问页表中的目录(Directory)最终查找到对应的物理内存:

图3-默认页的五层页表

如上图所示,如果我们使用Linux中默认的4KB内存页,那么CPU在访问对应的内存时需要分别读取PGD、PUD、PMD和PTE才能获取物理内存,但是2MB的大内存可以减少目录访问的次数:

图4-页表与大页

因为2MB的内存页占用了21位的地址,所以我们也不再需要五层页表中的PTE结构,这不仅能够减少翻译虚拟地址时访问页表的次数,还能够降低页表的内存占用。

CPU总可以通过上述复杂的目录结构找到虚拟页对应的物理页,但是每次翻译虚拟地址时都使用上述结构是非常昂贵的操作,操作系统使用TLB作为缓存来解决这个问题,TLB是内存管理组件(MemoryManagementUnit)的一个部分,其中缓存的页表项可以帮助我们快速翻译虚拟

分享 转发
TOP
发新话题 回复该主题