异步khugepaged扫描集成加速:类似THP,用户态界面hugetext_enabled控制单独设计。2M大页复用khugepaged集成。此外,由于hugetext和THP共享khugepaged,一些合格的代码页面也可以在THP=always中集成;关于加速部分,我们解决了代码段集成缓慢的问题,这也是我们对READ的改进ONLY_THP_FOR_FS带来的挑战
启动参数
基于透明大页异步整合大页的框架:
1代码段填充功能
多过程模型,代码段大小约10m。itlb应用程序-load-misses较高,约41%。
目前Linux内核支持的大页包括THP和hugetlb,其大小分别为:
添加hugetext链接脚本__pad_threshold的组合使用可以使应用程序对代码大页更加友好。
注:第一个地址2M对齐的初衷是mmapadr=mmappgoff,由于elfbinary和DSO可执行load段的pgoff一般为0,为了方便叙述,我们称之为地址2M对齐。
此前,我们描述了支持动态链接库和二进制文件本身的代码大页面方案。对于libhugetlbfs方案,它只支持二进制文件本身的大页面转换。虽然转换相对完整,但DSO不能同时使用大页面。显然,我们提供的hugetext_enabled方法比libhugetlbfs更完整,性能优势更大。填充功能主要是为了弥补代码段末尾的大量热点,libhugetlbfs自然可以做到,所以我们必须解决这个问题。言归正传,回到代码段填充。首先,代码段填充的具体内容是什么?
在全球页面粒度的支持下,Arm64也比X86更有趣,提供16KB和64KB两种选择。与4KB页面相比,这两个页面在TLB和cache上有明显的优化相关性,从而优化宏观指标。当然,并非所有的benchmark都表现出性能提升,比如SPECjvm2008和stream。当使用CONFIG_64KB时,我们发现许多指标的性能严重下降。除上述问题外,我还想再次啰嗦,CONFIG_64KB中,THP的大小确实有点“吓人”,有512MB。
为方便业务使用,我们扩展了启动参数和sysfs接口两种开启方式。
最后,带上一些私人商品。上述代码段填充主要是不重新编译应用程序的核心方法。另一种方法是在应用程序的链接脚本中添加“.=ALIGN",直接按2M对齐代码段,这样不需要填充或填充就更安全了。例如,使用一个简单的测试程序align.以out为例。设置链接脚本后,Section出现对齐:
$ readelf -l align.out
Elf file type is EXEC (Executable file)
Entry point 0x400520
There are 9 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R 0x8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001b 0x000000000000001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000200194 0x0000000000200194 R E 0x200000
LOAD 0x0000000000400000 0x0000000000a00000 0x0000000000a00000
0x0000000000010040 0x0000000000200008 RW 0x200000
DYNAMIC 0x0000000000400010 0x0000000000a00010 0x0000000000a00010
0x00000000000001d0 0x00000000000001d0 RW 0x8
NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R 0x4
GNU_EH_FRAME 0x000000000020004c 0x000000000060004c 0x000000000060004c
0x000000000000004c 0x000000000000004c R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000400000 0x0000000000a00000 0x0000000000a00000
0x0000000000010000 0x0000000000010000 R 0x1
Section to Segment mapping:
$ gcc main.c test.c -o align.out -Wl,-T ld-align.lds -z max-page-size=0x200000
1.整体结构和实现
04代码大页
大多数应用程序并不能完全保证其代码段2M对齐。如上所示,第一个r-xp有2M,其中我们的hugetext_enabled本身支持2M。为了确保其映射大小2M对齐,我们必须向后填充vma,其内容实际上来自下一个r-p数据。当然,在填充过程中,我们会判断填充后的大小不会超过原文件的大小,也不会与下一个r-p属性的vma重叠。以下是我们新引入的代码页面填充使能开关,例如将0x1000写入hugetext_pad_threshold,填充功能只有在填充内容超过4k时才能使用。
/sys/kernel/mm/transparent_hugepage/hugetext_pad_threshold
大伙对16KB、64KB还是又爱又恨。
上述代码大页方案主要包括三个部分:
在开发和测试过程中,我们的实现方案解决了与filetHP、linux社区和glibc社区p_align修复补丁相关的三个bug补丁。除上述部分外,我们已完成的自适应代码页面已完成,主要解决了x86平台使用代码页面过多的问题。详见“自适应处理”部分。
02大页现状
这些数据库至少有两个共同点:大代码段和高ITLBMiss。本文还根据这两个特点进行了优化。当然,大代码页面优化的目标并不局限于这三个数据库。
在透明页面的基础上,代码页面将支持扩展到可执行的二进制文件,包括过程二进制文件本身、共享库等可执行数据。与透明页面相比,代码页面只将相对较低和有限的可执行文件页面部分转换为大页面,从根本上避免了内存碎片和内存不足的问题。因此,由于代码数据和普通堆栈数据访问热对整体性能的影响不同,代码数据使用页面的性能远远大于相同重量的透明页面。因此,代码大页的推广和改进比透明大页更简单、更容易。
2快速试用
多线程模型,代码段约200m~280m。一般独家单机使用,性能验证过程中并发数要求高:121万,1500.THP本地验证不敏感。
映射的第一个地址对齐:这部分主要是在elfbinary和DSO建立映射的过程中,优先考虑2M对齐的虚拟地址空间,方便映射到2M大页。
在X86和Arm架构中,当我们提到THP时,我们可以认为它的大小是2MB。目前核心不支持1GBTHP,技术实现没有问题。社区中的一些人已经发布了相关的补丁..。回到这里,Arm64比x8hugtlb有两个大页面支持,主要是contigusbit,主要是针对tlbentry的优化。起源于16*4KB和16*2MB的64KB和32MB。
sysfs接口
Mysql是一个多线程数据库,其代码段大小一般在18m左右。THP不敏感,打开THP,性能提升不到3%左右。跨NUMA敏感,本地虚拟机32验证跨NUMA抖动约5~7%。
文章为作者独立观点,不代表股票配资公司观点