LinuxTransparentHugePage机制在云上大规模集群成本介绍。通过设计完备的透明巨页机制,实现云端大规模机器集群的快速推广应用,实现CPU性能和延迟优化10%+显着的双重收益。本文总结了透明巨页技术架构机制的实践经验,介绍了如何在保证服务稳定性的同时获取多场景性能收益。希望有兴趣的读者能有所启发。全文8456字,预计阅读时间22分钟。01背景随着商业和计算机硬件技术的不断发展,越来越多的内存机器(>=700G)出现以满足复杂计算处理的需要。页面容量功能可容纳越来越大的系统内存。在云端的大规模机器集群中,传统的内存页管理机制存在一定的性能问题。以一个典型的推荐系统服务为例,一方面,单次请求产生的中间数据比较大,另一方面,程序大量使用本地词典。&缓存等技术,显着增加响应单个请求所需的内存访问范围。通过perf统计一些典型线上程序的dtlb\_load\_misses.walk\_active和dtlb\_store\_misses.walk\_active的比值,也观察到页表缓存命中率不足。平均而言,大多数程序有5%-10%的时钟周期有miss导致陷入PageWalk的现象。目前,当机器硬件的大内存和系统内核技术具备时,透明大页面(TransparentHugePage)内存管理的应用成为可能。通过增加页大小,有望显着解决页表缓存命中不足的现象,从而普遍提高程序性能。但是,由于几个缺陷,主要集中在显着增加内存使用,频繁的回收和重组带来额外的开销,并且是不可控的。随机滞后。基于这些因素,目前业界对透明巨页机制的普遍看法是负面的。问题排查到透明巨页,目前对服务的影响尚无定论。这也是透明巨页技术应用中的一个难题。02大页内存技术的演进内存是计算机上非常重要的资源。程序的加载和运行、CPU的指令、数据的获取都依赖于内存的使用。因此,内存访问性能是影响计算机性能的一个非常重要的因素。现代Linux系统内存分配的主要流程如下,如图1所示:1.应用程序调用内存分配函数(malloc、free、realloc、calloc),系统调用brk或mmap进行分配内存并申请一个虚拟内存地址空间。2、在虚拟内存到物理内存的映射过程中,通过请求MMU分配单元,根据虚拟地址计算出地址所属的页,进而得到页映射表(PageTable)项所在的物理内存地址located是根据页映射表的起始地址计算出来的。address,根据物理地址,在cache的TLB中查找entry的内容,如果entry不在TLB中,则从内存中加载它的内容到TLB中。其中:虚拟内存(_VirtualMemory_):现代操作系统普遍采用的一种技术,每个进程都有独立的逻辑地址空间,内存被分成多个大小相等的块,称为页面(Page)。每一个page都是一个连续的地址,对应一块物理内存叫做pageframe,通常page和pageframe的大小是相等的。MMU(_Memory-ManagementUnit_):内存管理单元,负责管理虚拟地址到物理地址的内存映射,实现每个用户进程都有自己独立的地址空间,提供硬件机制的内存访问权限检查,保护内存每个进程使用的内存不会被其他进程破坏。PageTable:虚拟内存到物理内存的页面映射关系存储单元。TLB(_TranslationLookasideBuffer_):高速虚拟地址映射缓存,主要是为了提高MMU地址映射处理的效率,增加了缓存机制,如果存在,可以直接取出映射地址使用。____△____图1Linux内存分配机制(虚拟+物理映射)2.1标准HugePageHugepages通过增加单位页的大小来替代传统的4KB内存页,以适应越来越大的系统内存,使操作系统能够支持现代硬件架构的大页面容量功能,减少MMU管理开销,提高内存处理性能。主要有两种格式大小:2MB和1GB,2MB块大小适用于GB级内存,1GB页块大小适用于TB级内存;2MB是默认页面大小。优点:无需交换:不存在因内存空间不足而导致页面交换进交换出的问题。减轻TLBCache的压力:在内存大小相同的情况下,管理的虚拟地址数量减少,从而降低了CPUCache可以缓存的地址映射压力。减少页表负载:内存页数会减少,从而需要更少的页表,节省页表占用的内存量。消除页表查找负载:不需要页表查找,因为不需要替换页面。提高内存的整体性能:页面变大后,处理的页面变少,可以明显避免访问页表时可能出现的瓶颈。缺点:需要合理设置避免内存浪费:在操作系统启动时动态分配和保留,不会更换共享内存,使用HugePage的内存不能被其他进程使用,所以合理设置该值避免造成内存浪费。静态设置不能自适应:如果增加了HugePage或者增加了物理内存,或者当前服务器增加了新的实例发生变化,需要重新设置需要的HugePage大小。使用方法:1)查看机器标准大页面状态,可以使用如下命令查看大页面状态:grepHuge/proc/meminfoHugePages_Total:0HugePages_Free:0HugePages_Rsvd:0HugePages_Surp:0Hugepagesize:2048kB2)大页通过设置vm.nr\_hugepages参数修改大页数,大页的分配需要连续内存,机器长期运行有内存碎片,可能不满足分配需要。通常,启动时需要分配设置。例如,以下命令设置大页面配置:sysctl-wvm。nr_hugepages=203)使用大页面的应用程序需要适配mmap系统调用或shmat和shmget系统调用来使用大页面。一般的应用进程无法访问这个巨大的页面空间。2.2透明大页面(TransparentHugePages)标准大页面可以提高性能,但配置和管理有困难,难以手动管理,通常需要对代码进行较大改动才能有效使用,不能通用对应用程序透明巨页的访问和使用从RHEL6(kernel>=kernel-2.6.32)开始引入。在标准大页面的基础上,通过一个抽象层,可以自动创建、管理和使用传统的大页面。为了提高内存管理的性能,解决手工管理大页面的问题,透明大页面降低了系统管理员和开发人员使用传统大页面的复杂性。优点:与标准大页相比,操作系统动态管理大页分配,支持大页分配、大页->普通页换出和拆分,根据具体应用使用情况自适应调整分配。使用对应用透明,开源社区对大部分应用持续测试优化适配,支持多种大页应用配置,满足多种场景的分配需求缺点:THP在运行时动态分配内存,可能带来CPU开销和运行时内存分配的上升问题。在THP同步应用模式下,当分配失败时触发应用,会导致应用出现一些随机卡顿。使用方法:TransparentHugepage有效方式:TransparentHugepage对匿名内存的支持可以完全禁用,或者只在MADV\_HUGEPAGE区域启用(避免消耗更多内存资源的风险),或者在系统范围内启用,你可以实现通过以下方法之一:echoalways>/sys/kernel/mm/transparent_hugepage/enabledechomadvise>/sys/kernel/mm/transparent_hugepage/enabledechonever>/sys/kernel/mm/transparent_hugepage/enabledHugepagememorypagedefragmentationControl:/sys/kernel/mm/transparent_hugepage/defrag大页内存整理方式:具体使用如下:echoalways>/sys/kernel/mm/transparent_hugepage/defragechodefer>/sys/kernel/mm/transparent_hugepage/defragechodefer+madvise>/sys/kernel/mm/transparent_hugepage/defragechomadvise>/sys/kernel/mm/transparent_hugepage/defragechonever>/sys/kernel/mm/transparent_hugepage/defrag整体内存页技术总结:普通页、标准大页和透明巨页页面的主要技术特点和优缺点如下:03整体解决方案大型在线服务集群开启透明巨页,在实践中面临的一些问题和挑战:1.大规模机器集群,多应用混合分布,环境复杂,大部分程序不能很好的适应大页面的分配。如何控制大页面生效的方式,将对混合分布的应用产生可控的影响。2、如何提高应用访问巨页机制的效率,降低服务访问成本,实现普适推广。根据云上大规模集群的机器硬件情况,内核版本和服务混合分布的特点,整体巨页机制的技术方案设计,从机器内核(Machine&Kernel)三个层次,混合分发容器(container)和应用服务(Applicatoin)考虑,保证机器大页面环境,在容器中实现根据应用定制开启和关闭大页面的功能,同时兼容默认标准页面,在access中考虑基于内存分配库的通用访问,对业务方透明。下面主要从三个层面介绍大页面机制的设计思路:____△____图2大页面机制的技术架构3.1机器内核在机器内核层面,大页面的使用主要有TransparentHugePage和There是普通大页(Hupgetlb)的两种方法,透明大页的具体工作方式分为显式启用(ExplicitEnable)和隐式启用(ImplicitEnable);应用模式中有异步应用(AsyncDefrag)和同步应用(SyncDefrag))。在实践中,根据云上集群混合分布和服务常驻进程居多的特点,选择了透明大页+显式开启+异步申请的模式。动态重组开销,但目前必须在上电时预留,透明大页面在渐进阶段适应性更强。显式启用(ExplicitEnable)大多数应用所依赖的malloc并不能很好地适配透明大页,这会带来更大的内陆冗余和更大的碎片重组开销。Explicitenable可以随着程序malloc机制逐步升级如果开启,也实现了混合环境对其他应用的影响可控。异步应用(AsyncDefrag)同步重组在重启期间会出现明显的卡顿,运行期间可能会出现零星的随机卡顿。异步方式可以尽可能避免卡顿的发生。由于集群几乎都是驻留进程,异步模式通常也足以提供足够的hugepage填充率。机器内核参数设置启用:echo'never'>/sys/kernel/mm/transparent_hugepage/defragecho'madvise'>/sys/kernel/mm/transparent_hugepage/enabled禁用:echonever>/sys/kernel/mm/transparent_hugepage/enabledechonever>/sys/kernel/mm/transparent_hugepage/defragusage:#查看整机grepAnonHugePages/proc/meminfoAnonHugePages:612832kB#查看进程cat/proc/pid/smaps|awk'/AnonHugePages/{h+=$2}/Anonymous/{a+=$2}END{printa,h,h/a}'#Hugepage使用情况和申请状态egrep'trans|thp'/proc/vmstatnr_anon_transparent_hugepages2018thp_fault_alloc6021thp_fault_fallback0thp_collapse_alloc201thp_collapse_alloc3.Conplock_failedPass20thpcontainer集群上的应用部署,在物理机上,主要是利用基于pass的容器虚拟化技术,实现彼此之间资源和使用的隔离,保证独立干净的运行环境应用。目前透明大页对机器操作系统的内核版本有要求(Kernels>=kernel-2.6.32),所以启用大页的服务需要支持根据内核版本进行调度部署,保证运行环境大页面。其次,针对PageCache场景添加安全监控和相应的处理机制。具体如下:亲和部署(KernelVersionAffinity)透明大页异步重组,依赖于一个高版本内核,在集群多版本内核共存的情况下,容器可以保证大页环境通过亲和内核部署;这样可以降低集群对全升级内核资源的依赖,实现大页面对部分服务的快速应用,通过同步逐步升级内核支持更多的大页面环境,实现逐步全覆盖。代码锁(mlock)代码段锁mlock机制,部分机器缺少PageCache。异步重组和进一步回收可能会导致代码段消除并导致滞后。目前的实施观察并不明显。3.3应用服务层(Application)**应用服务层,访问大页面需要应用内存分配的兼容处理。目前,出于性能考虑,内存使用主要是通过内存条间接使用。我们对内存条做了针对性优化,对业务使用透明,实现了常用应用的快速接入。其次,可以通过直接使用大页访问相应的数据和字典服务,减少内存库管理的开销,进一步提高处理性能。具体描述如下:公共业务逻辑(CommonBusiness)优化内存bank以适应大页的分配。接口统一使用环境变量控制应用大页面是否启用,提高常规内存使用性能,降低访问成本,实现应用透明。快速访问。大内存消耗细粒度管理(DB&Dict类)对于大内存消耗场景,比如数据库或者字典服务,消耗的内存块大小是比较固定的。这样就可以通过独立的mmap&madvise使用大页,减少内存bank带来的额外开销,追求极致的性能优化。3.4辅助设施(Assistant)为了更好的控制和了解机器和应用透明大页的使用,设计了完善的透明大页监控机制,实现有效的性能指标监控,方便对大页相关内核参数的支持页。调整。Hugepageutilizationgeneralhugepagemonitoringlibrarylib支持对任何服务的通用访问,填补了非云环境的监控需求;云端容器内嵌透明大页监控,透明实现查看应用内存大页覆盖指标。THP内核调优建立machine-granularityKhugepaged进程消耗指标监控内核大页;通过对大页内核参数的优化调整,全面的Khugepaged重组大页时间和资源消耗,保证应用更好的利用大页。04在关键技术工程实践中,通过大页内核参数调优+内存条优化,应用可以充分利用大页内存,最大限度地发挥大页内存处理性能;同时优化内存占用,将内存增长控制在合理范围内。优化目标主要有以下两个方面:提高大页的覆盖率由于混合机环境和异步分配大页的机制,不一定保证机器内存的大页被分配和使用。如何调整大页内核参数,优化内存bank,提高Applyhugepage使用率。如果在测试中发现系统默认的THP参数不是最优的,JeMalloc内存库在大页的使用上不足,可以通过优化来最大化使用大页的性能。降低内存增长速度对于页面大小从标准的4KB增加到2MB时不能很好适应的应用程序,可能会有一定的内存增长。通过调整内存bank参数,降低了启用大页内存带来的内存增长开销,控制在10%左右的合理范围内。5.1调整大页面相关参数4.1调整大页面相关参数结合内核大页面参数和Malloc库参数,提高服务大页面分配覆盖率,降低内存开销。1.透明大页内核参数调优通过优化相关内核参数,综合CPU开销和重组速度,提高大页分配效率。内核大页面管理进程khugepaged进行大页面的分配、聚合、拆分等操作。主要参数如下:alloc\_sleep\_millisecs:碎片整理间隔,如果本次分配大页失败,等待下一次分配尝试的时间,单位毫秒。max\_ptes\_none:指定在将一组小页面合并为一个大页面时可以分配多少个额外的小页面。pages\_to\_scan:每次扫描的页数。scan\_sleep\_millisecs:扫描间隔,单位毫秒。对应常驻服务,可以配置如下参数组合,以低开销实现大页面重组,保证更好的大页面覆盖。echo'100'>/sys/kernel/mm/transparent_hugepage/khugepaged/alloc_sleep_milliseccho'511'>/sys/kernel/mm/transparent_hugepage/khugepaged/max_ptes_noneecho'2048'>/sys/kernel/mm/transparent_hugepage/kanepaged/pages_to_100'>/sys/kernel/mm/transparent_hugepage/khugepaged/scan_sleep_millisecs2。Malloc库分配参数调优以JeMalloc为例,默认初始化内存块(arena)大小为本机CPU核数*4,进程启动后不能动态修改。实际上,应用程序通常不需要那么多内存块。一般可以根据逻辑核心数来配置。这样可以优化大页内存下的内存开销。4.2应用层内存池技术利用内存池进一步提高大页的使用效率,减少碎片内存长期占用造成的内存膨胀,优化和减少内存占用。目前主要从以下两个方面进行优化。内存池-长生命周期碎片内存利用内存池技术对整块内存进行持续分配和管理,避免重复申请和释放,解决了长期缓存场景下小内存碎片长期保留的问题,从而在大量增加内存。自定义大页面-大内存应用场景程序使用大内存操作,大小相对固定,如DB,字典服务等,大内存使用THPmadvise开发管理,小内存使用Malloc库来实现进一步提高性能。自定义大页,主要步骤:1.HugePage大小对齐申请size_tmem_size=num*(2UL<<20);//2MBmultipleauto*ptr=(char*)mmap(nullptr,mem_size,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0);2.使用MADVISE区域标记通过接口intmadvise(void*addr,size\_tlength,intadvice)使用标记MADV\_HUGEPAGE大页内存,如:intret=madvise(ptr,mem_size,MADV_HUGEPAGE);if(ret!=0){//失败std::cout<<"失败ret:"<
