Yak: A High-Performance Big-Data-Friendly Garbage Collector

0 概念

generational假设: 最近分配的对象最可能很快地就不可用了;大多数对象生命期较短。

epochal假设:许多数据路径对象具有相同的生命期,可在一个时期结束后被一起回收。

控制路径 & 数据路径:一个典型的大数据系统通常会逻辑清晰地区分控制路径和数据路径,如图1所示:
这里写图片描述

控制路径执行集群管理和调度,在节点之间建立通信信道,与用户交互,即解析查询并返回结果。数据路径主要是将一些数据操作功能连接在一起,以形成数据处理流水线。

控制路径的行为类似于常规程序,逻辑复杂,但只创建少量对象,所创建的对象一般遵循generational假设。而数据路径的代码逻辑简单,但创建对象较多,所创建的对象不遵循generational 假设,对象的生命期较长,通常会跨代。

CS & DS:Yak将堆分为控制空间(CS)和数据空间(DS),控制路径中的对象在控制空间中分配;数据路径中的对象在数据路径中分配。

时期:一个时期是一个数据转换代码块的执行。对于 Hyracks,一个时期覆盖了(用户定义的)数据集操作符(即,通过open/close);对于Hadoop,包含了Map和Reduce任务的主体(即,通过setup / cleanup); 对于GraphChi,每个时期包含beginSubInterval回调指定的的子间隔的主体。

这里写图片描述

1 现有的问题

问题1:
大多数“大数据”系统使用用托管语言开发,导致内存管理代价较高。如,垃圾回收(GC)占执行时间的近50%。

问题2:
大数据系统在运行时创建了大量对象,如果手动将大量对象移出管理堆,则增加了开发人员的负担。

问题3:
现有的GC算法与对象特性不匹配。
对象大都创建于数据路径,具有跨代行为,不遵循generational假设。而现有的GC算法,如generational GC,是基于generational假设来回收堆的。GC将对象分为新代和旧代。对象最初分配于新代。当护理GC运行时,它会识别旧代可访问的新代对象,并将其升级为旧代,然后再回收剩余的整个新代。而旧代很少被垃圾回收。GC花费大量时间来识别新代中的对象并将其移动到旧代中,仅回收很少的空间。

基于区域的内存管理: 已经采用了epochal假设,但需要复杂的静态分析,无法扩展到大型系统或重型手动重构,并未被大数据系统的GC采用。

2 方案

2.1 整体架构
Yak将托管堆分为控制空间(CS,control space)和数据空间(DS,data space),控制路径中的对象在CS中分配,数据路径中的对象在DS中分配,分别采用基于代和基于区域的算法自动管理内存。

2.2 评价体系
将Yak和Parallel Scavenge (PS)— Oracle JVM的默认GC进行比较。分别采用Hyracks、 Hadoop、GraphChi三种框架进行评估,对于每个框架,分别挑选了3个具有代表性的程序,如表1所示:
这里写图片描述
表2显示了数据集和堆配置。
这里写图片描述
集群配置:11个节点,每个节点都有2个 Xeon(R) CPU和E5-2640 v3处理器,32G内存,一个SSD,运行CentOS 6.6系统。

将Hyracks和Hadoop运行于整个集群上,GraphChi运行于其中一个节点上运行,因为它是单机系统。Yak的CS和DS的内存大小比值为1/10。DS中每页的大小默认为32KB。让每个程序迭代3次。第一次迭代是给JIT热身,后两代之间性能的差异可以忽略(如,少于5%)。

3 Yak要解决的问题

问题1:如何使CS和DS的两种堆管理形式很好的共存于一个GC中。

问题2:如何正确管理DS区域。即,如何正确处理那些在时期内分配,但转义到其他时期或控制路径中的对象。当时期结束时释放整个区域可能会导致程序失败。如果手动管理的话,如Facade 和Broom,会增加开发人员负担。

问题3:如何有效管理DS区域。包括有效跟踪并迁移转义对象。如果监视每个可访问转义对象的堆,会导致过高的开销。

解决思路:
问题1:以常规方式管理CS的generational回收器应该忽略某些输出引用,以免妨碍到DS管理。并跟踪传入的引用,以避免释放DS对象引用的CS对象。

问题2:自动跟踪并标识转义对象,然后在区域释放期间,使用升级算法来转移转义对象。

问题3:只在堆写之前进行轻量级的检查,而非堆读取时。为保证内存正确(没有对象在存活期间被释放),在释放区域新时,采用轻量级的“停止世界”处理,不引入明显停顿。

4 设计概述

何时创建 & 释放DS区域?
当一个时期开始时,在DS中分配一个区域,一个时期结束时,释放区域。该区域会保存时期内创建的所有对象。为了实现跨不同大数据系统的统一处理,Yak期望用户注释是成对的,epoch_start和epoch_end。这些注释在运行时被转换为两个本地函数调用,以告知JVM时期的开始与结束。注释的放置无需手动操作。

在实践中,需要考虑关于时期概念的更多问题。其中一个是关于时期的嵌套关系。为获得性能优势,Yak支持区域嵌套—内时期访问不到的对象可在外时期结束之前被回收,避免了内存增长过快而造成的内存占用。另一个问题是,当多个线程同时执行数据处理代码的相同片段时,如何创建区域。Yak为每个时期的动态实例创建区域。当两个线程执行时期代码的相同片段时,他们获得自己的区域而无需考虑同步问题。

这里写图片描述

这里写图片描述

如何正确并高效地释放区域?
少量的对象可能比他们所处的时期长,必须被标识,并在区域释放时小心处理。Yak必须自动完成两项关键任务:(1)标识转义对象。(2)为这些对象进行目标重定位。

对于第一项任务,Yak使用高效的算法来追踪跨区域/空间的引用,并在运行时为每个区域记录所有传入的引用。在区域释放之前,Yak将这些引用作为根集合,以计算区域中转义对象的传递闭包。

这里写图片描述

在释放时,如在其他线程正在访问时计算转义对象的传递闭包,可能会导致不完全闭包。另外,当其他行程运行时,不应并发地移动对象,否则可能会引起数据竞争。为此,Yak使用轻量级的“停止世界”处理,以保证在释放时内存是安全的。当一个线程到达时期结束时,Yak暂停所有正在运行的线程,扫描它们的栈,计算释放区域内所有潜在活对象的闭包。在所有的修改线程恢复前,将这些对象移动到各自的目标区域。

5 实现

在Oracle的JVM OpenJDK 8 (build 25.0-b70)中实现了Yak。除了基于区域的技术,还修改了两个JIT编译器(C1和Opto),解释器,对象/堆布局,和Parallel Scavenge收集器,以管理(CS)。

5.1 区域 & 对象分配

区域分配: 当JVM启动时,操作系统会根据用户指定的堆大小为其预留一个虚拟地址块。Yak将此地址空间分为CS和DS,它们之间的比例由用户通过JVM参数指定。刚开始时,Yak仅需少量内存,初始空间用完后继续扩大。当一个时期开始时,Yak会在DS中创建一个区域。一个区域包含一个页表,其大小可由JVM参数指定。

堆布局: 图6显示了Yak所维护的堆布局。CS与generational GC所维护的Java堆相同,除了新添加了一个记忆集。DS则大一些,包含了大量区域,每个区域都有一个页列表。

这里写图片描述

在DS中分配对象: 当执行位于一个时期内时,将所有对Eden空间(比如,新代)的请求重定向到新Region_Alloc函数。Yak过滤掉JVM的元数据对象,如类加载器和类对象,使其不在区域中分配。区域管理器使用快速碰撞指针算法试着在页表的最后一页分配对象。如果该页空间不够,它将创建一个新页,并添加到页表。如果一个大对象无法装入一页,则请求一个可以装入该对象的特殊页。出于性能的考虑,不移动大对象。

5.2 追踪区域间的引用

在较高的层面上,Yak用3步实现了有效跟踪所有区域间/空间的引用。

第一,在每个对象的空间的头部添加一个4字节的re字段,以记录区域信息。在分配对象时,根据根据区域ID更新re字段。CS使用特殊的ID。

第二,修改了写障碍(即,当堆写下指令a.f=b时,执行一个代码片),以检测并记录基于堆的区域间/空间引用。算法1中显示了修改后的写障碍。

这里写图片描述

第三, 当epoch_end触发时,Yak检测并记录基于本地栈的区域间引用和基于远程栈的引用。这些算法被显示在算法2中的第1-4行和第5-10行。

通过追踪对转义对象的引用可以驻留的3个地方—堆,本地栈、远程栈,下面在细节上描述了Yak是如何追踪区域间的引用的。

这里写图片描述

(2)在本地栈: 当一个对象被运行期外的栈变量引用时,会转义,如图7(a)所示。第3行分配的对象的引用被分配给栈变量a。因为a在一个时期结束后仍活着,所以释放该对象是不安全的。

这里写图片描述

这里写图片描述

5.3 区域释放

算法2显示了在每个时期末触发区域释放算法。此算法计算转义对象的闭包,将转义对象转移到其目标区域后,回收整个剩余区域。

这里写图片描述

寻找转义根: 一个区域有3种转义根。第一,是r的记忆集中所记录的指向区域间/空间的引用。第二,释放线程时,被本地栈所引用的对象。第三,被其它线程中的远程栈所引用的对象。

由于区域间/空间的引用早已被写障碍所捕获,因此首先通过的本地栈来标识在时期内转义的对象。如算法2的第1-4行所示。

接下来,Yak标识通过远程栈转义的对象。为此,Yak需要将线程同步(第5行)。当远程线程暂停时,Yak扫描其栈变量,并返回一个被这些变量所引用的位于r中的对象的集合。每个这样的对象(远程对象)都要被明确标记为根,并在计算传递闭包之前(第11行)移动到CS(第10行)。

没有线程会被恢复,直到完成闭包运算并将所有的转义对象移动到它们的目标区域。注意,即便远程线程的栈没有引用任何中的对象,让继续前进也是不安全的。

所有的转义对象都会被重新分配,然后释放整个区域,其所有页面会被重新放回空闲页表(第13行)。

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

6 评价

6.1 延迟和吞吐量

图10描述了Yak和PS性能的详细比较。表3通过显示总体运行时间、GC、应用程序时间,以及内存消耗,总结了Yak的性能提升之处。

这里写图片描述

这里写图片描述

对于 Hyracks,Yak的所有评估指标都优于PS。虽然Yak的写障碍会带来开销,但其捕获的引用几乎都是区域内引用,不会触发写障碍上的慢路径(即,更新记忆集)。Yak还提高了(非GC)应用程序的性能—这是因为PS仅对小对象执行线程-本地分配,对于大对象,必须在共享堆中分配,受锁保护。然而,在Yak中,所有对象都是在线程-本地区域中分配的,因此这些线程可以并行分配对象。无锁分配是Yak提升应用程序性能的主要原因,因为在程序中经常需要分配大对象。

相对于Hadoop和GraphChi,Yak大大减少了GC时间和总体运行时间,但却增加了应用程序时间和内存消耗。应用程序时间更长是因为:(1)内存回收(即,区域释放)从GC转移到了应用程序。(2)触发写障碍以记录大量引用。

Yak大大缩短了GC引起的暂停。当Yak启动后,Hyracks、Hadoop和GraphChi中的最大暂停(回收内存)时间分别是1.82,0.55,和0.72秒。而在PS下,最大暂停时间分别是35.74,1.24和9.48秒。

随着堆的增大,由于运行的GC数量较少,PS会有少量的性能提升,而Yak性能提升不大,因为CS毕竟只是一小部分。

6.2 内存使用

这里写图片描述

通过定期运行pmap来了解Java进程(对于应用程序和GC)的总体内存消耗。图11比较了不同配置下的Yak和PS的内存占用情况。对于Hyracks和GraphChi,内存占用通常是稳定的,而Hadoop则是波动的。因为Hadoop运行多个JVM,不同的JVM会被经常性地创建和销毁。由于JVM声明的内存在其终止之前不会归还给操作系统,对于Hyracks和GraphChi来说,内存消耗总是增加的。而Hadoop消耗的内存总量会经常性的下降,由于其JVM进程的频繁创建和终止。

对于Hyracks,Yak通常比PS内存消耗更低。这是因为当一个数据处理线程结束时,Yak可以立刻回收内存,而GC通常会有一个延迟。对于Hadoop和GraphChi,Yak的内存消耗略高于PS,主要的原因在于在数据路径和已经分配的区域中创建了大量控制对象,这些对象的生命期通常比包含它们的区域短,PS可以比Yak更有效地对其回收。

空间开销: 为理解每个对象头部额外的4字节字段的开销,将GraphChi和修改后的 HotSpot 1.8.0 74进行比较,并将堆消耗的峰值同Yak比较(通过定期运行pmap)。发现差别(即,开销)相差不大,按照GraphCh的3个基准,开销从1.1%变化到20.8%,平均为12.2%。

6.3 性能不足

Yak是基于典型的大数据系统构建的,仅有一小部分对象从数据路径转义控制路径,因为表4显示#CSR和#TR的数量比值通常较小。

这里写图片描述

图12描述了页大小不同时,Yak的执行时间和内存性能。页大小不同时,执行时间变化不大(比如,在149秒与153秒之间变化)。而内存消耗的峰值却随着页的增大而增大。

这里写图片描述

写障碍和区域释放时Yak应用程序开销的两个主要来源,如图10所示,按照基准,区域释放时间占总执行时间的2.4%~13.1%。为了解障碍的成本敏感性,手动修改了 GraphChi的执行引擎,在线程加载滑动分片和执行更新之间强制执行障碍。对于 GraphChi上的3个程序发现非暂停时间增加了24.5%,表明写障碍是主要的瓶颈。

可扩展性: 用Yahoo Webmap的4个大小分别为9.4G,14G,18G的数据集来运行Hyracks ES。图12表明Yak的性能通常优于PS,随着数据集的增大,性能改善也在增加。

6 局限

写障碍是性能瓶颈。

第一,为了实现写障碍,现有的GC都有手工制作好的/经优化的汇编代码,而Yak没有基于汇编的优化。期望这个优化实现后,可以降低写障碍开销。

第二,添加额外的、定义好的细粒度时期也许会进一步改善性能。例如,如果可被静态对象访问的对象能在Hadoop的CS中创建,就可以显著减少空间引用。

在本次实验中,未实现程序重构,但相信是可以显著提升性能的:取决于开发者用多少注释来获得其想要的额外性能。

参考文献
Yak: A High-Performance Big-Data-Friendly Garbage Collector
Khanh Nguyen, Lu Fang, Guoqing Xu, and Brian Demsky; University of California, Irvine; Shan Lu, University of Chicago; Sanazsadat Alamian, University of California, Irvine; Onur Mutlu, ETH Zurich

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
智慧校园2.0是高校信息化建设的新阶段,它面对着外部环境变化和内生动力的双重影响。国家战略要求和信息技术的快速发展,如云计算、大数据、物联网等,为智慧校园建设提供了机遇,同时也带来了挑战。智慧校园2.0强调以服务至上的办学理念,推动了教育模式的创新,并对传统人才培养模式产生了重大影响。 智慧校园建设的解决之道是构建一个开放、共享的信息化生态系统,利用互联网思维,打造柔性灵活的基础设施和强大的基础服务能力。这种生态系统支持快速迭代的开发和持续运营交付能力,同时注重用户体验,推动服务创新和管理变革。智慧校园的核心思想是“大平台+微应用+开放生态”,通过解耦、重构和统一运维监控,实现服务复用和深度融合,促进业务的快速迭代和自我演化。 智慧校园的总体框架包括多端协同,即“端”,它强调以人为中心,全面感知和捕获行为数据。这涉及到智能感知设备、超级APP、校园融合门户等,实现一“码”或“脸”通行,提供线上线下服务端的无缝连接。此外,中台战略是智慧校园建设的关键,包括业务中台和数据中台,它们支持教育资源域、教学服务域等多个领域,实现业务的深度融合和数据的全面治理。 在技术层面,智慧校园的建设需要分期进行,逐步解耦应用,优先发展轻量级应用,并逐步覆盖更多业务场景。技术升级路径包括业务数据化、数据业务化、校园设施智联化等,利用IoT/5G等技术实现设备的泛在互联,并通过人工智能与物联网技术的结合,建设智联网。这将有助于实现线上线下一网通办,提升校园安全和学习生活体验,同时支持人才培养改革和后勤管理的精细化。 智慧校园的建设不仅仅是技术的升级,更是对教育模式和管理方式的全面革新。通过构建开放、共享的信息化生态系统,智慧校园能够更好地适应快速变化的教育需求,提供更加个性化和高效的服务,推动教育创新和人才培养的高质量发展。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值