解释Azul的"无动作"垃圾收集器

kik*_*ito 41 garbage-collection

我刚看过这个:

http://www.artima.com/lejava/articles/azul_pauseless_gc.html

虽然我对编译器有一些经验,但我没有做任何与垃圾收集有关的事情; 对我来说是一个很大的黑盒子.

我一直在努力理解文章中提到的问题.我理解这个问题(执行大多数垃圾收集器时有一个暂停),我知道他们声称他们的实现没有那个问题.但我不明白为什么/如何在第一时间发生问题(似乎在原始文本中可以理解这一点),因此我不明白为什么他们的解决方案可能会起作用.

有人可以向我解释一下:

  1. 为什么垃圾收集者一般会暂停
  2. 为什么Azul的gc没有这个问题?

当以图形方式解释时,我倾向于更好地理解这种事情 - 可能用代码编辑器完成的小内存模式就足够了.

谢谢!

小智 49

他们谈论压缩堆时不可避免的暂停.你会看到,当你分配和释放大量不同大小的对象时,你就会对堆进行分段(就像你分割你的硬盘一样).当碎片变得太极端,你必须清理/整理/紧凑通过预留的内存大块,还有移动的所有对象(无任何碎片)堆和使用他们的前位置作为存储新块没有在任何物体,即没有碎片.

执行此操作时,您将对移动的所有对象的所有引用无效.要防止这种情况,必须防止使用引用预压缩对象位置的引用.到目前为止最简单的方法是暂停整个应用程序,移动对象,然后更新所有引用.当然,这会产生很大的开销.

因此,Azul提出的解决方案是这样的:它们建立了一个"读屏障",允许GC拦截解除引用,这样他们就可以懒惰地更新实际使用的引用.


Gra*_*ems 17

为什么垃圾收集者一般会暂停?

GC通过跟踪从一组全局根(全局变量,线程堆栈和CPU寄存器)开始的可到达堆块来工作.GCs位于从快照到动态的滑动范围内.快照GC可以从全局根和堆拓扑的快照开始工作.当变换器运行时,动态GCs逐步更新它们对堆的解释.

跟踪不是"为什么垃圾收集者一般会有这种停顿",暂停的原因更多:对象重定位是主导的.

但是即时对比快照跟踪器及其相对效率:即时跟踪可以更快速地进行快照跟踪器.您在描述[VCGC]时引用的同一篇论文将Azul先前的非世代Pauseless收集器分类为精确的波前[3]示踪剂:

"...大多数实际的收集器使用波前的保守抽象而不是这里提供的精确定义.也就是说,波前是以对象粒度跟踪的.但是,精确的波前不仅仅是理论上的,而且最近已经在硬件中使用了Azul Java服务器的辅助收集器,它在每个指针[2]中都有一个"未标记"位."

Azul的C4具有这种品质,但使用纯软件,自我修复的LVB读取屏障实现了这一目标.

完全快照GC获得高吞吐量,因为收集器几乎完全独立于mutator运行但具有高延迟,因为拍摄快照会导致暂停.由于改变器和GC之间的细粒度通信,因为一切都是以递增的方式完成但吞吐量低,因此全速运行的GC可以获得低延迟.

精确的波前跟踪器同样有效(从本文讨论的"不花时间在不需要的对象上"的观点)作为一种世界上的跟踪器,根据定义,它也具有一个前沿波形.与基于快照的方法相比,精确的波前扫描不会以任何方式减慢吞吐量,或者需要收集器和增变器之间的任何更多通信.它具有良好或更好的吞吐量,因为它的精确性确保它永远不必重复任何跟踪工作.

为什么Azul的gc没有这个问题?

他们仍然有这个问题,但他们通过在硬件中实现读屏障来减少它.之前已经提出了读取障碍,但是软件读取障碍会使吞吐量降低太多,因为指针读取比写入更常见.

如上所述,如果"问题"由于即时与快照行为导致效率低下,那么C4没有它,因为它是一个精确的波前跟踪器.此外,Azul的C4收集器不需要或使用硬件读取障碍,因为它在vanilla x86和Linux系统上运行,并且在基于快照的跟踪收集器所做的硬件上实现了更好的吞吐量(参见[1]中的吞吐量比较). .

然而,问题中的"问题"被称为"为什么垃圾收集者一般会暂停?" 波前精确度(或不是)在垃圾收集器中的主要暂停几乎没有.并存和大部分并发(即使效率低于C4)标记确实存在,但它们的收集器仍然暂停.问题是跟踪只是收集的一部分.追踪只会告诉你什么是活着的以及它在哪里.它不会给你任何回忆,它肯定不会破坏碎片化的内存.该主题在各种学术论文中进行了深入讨论(参见C4论文[1]的大量参考文献).

压缩(和隐含的对象重定位)似乎是当前在服务器JVM上运送收集器的致命弱点,以及固有地导致它们进行[大]暂停的事情.将一个对象从一个地方重新定位到另一个地方的简单操作意味着在程序使用它们之前必须修复指向该对象的所有引用.对于大多数商业运输收集器,这意味着停止世界暂停,使应用程序在修复引用时不运行.

C4利用自我修复LVB屏障([2]中引入的一种新型读屏障,并在[1]中以大量软件形式大量使用),以避免在允许应用程序运行之前修复引用.这就是它如何避免其他收藏家最终不得不采取的暂停.与以前的非自愈障碍相比,自我修复质量将读取屏障的动态成本降低了几个数量级(例如学术工作中其他并发压实机中使用的小溪式屏障,以及某些实际的时间收集者).这种显着降低的读屏障成本的结果是它可用于分代收集和服务器级JVM.

[1]:"C4:连续并发压缩收集器" http://dl.acm.org/citation.cfm?id=1993491&dl=ACM&coll=DL&CFID=85063603&CFTOKEN=84074207 [2]:"Pauseless GC算法" http: //static.usenix.org/events/vee05/full_papers/p46-click.pdf [3]:"正确性保留并发垃圾收集算法的推导"www.srl.inf.ethz.ch/papers/pldi06-cgc. PDF格式

(Graham Thomas,EMEA Azul Systems技术经理)


Jon*_*rop 8

为什么垃圾收集者一般会暂停?

GC通过跟踪从一组全局根(全局变量,线程堆栈和CPU寄存器)开始的可到达堆块来工作.GCs位于从快照到动态的滑动范围内.快照GC可以从全局根和堆拓扑的快照开始工作.当变换器运行时,动态GCs逐步更新它们对堆的解释.

完全快照GC获得高吞吐量,因为收集器几乎完全独立于mutator运行但具有高延迟,因为拍摄快照会导致暂停.由于改变器和GC之间的细粒度通信,因为一切都是以递增的方式完成但吞吐量低,因此全速运行的GC可以获得低延迟.

实际上,所有地方选区都介于这两个极端之间.VCGC主要是一个快照GC,但它使用写屏障来保持收集器了解堆拓扑的变化.Staccato是世界上第一个并行和并发和实时GC,但它仍然批量处理一些操作,以保持堆栈分配的效率.

为什么Azul的gc没有这个问题?

他们仍然有这个问题,但他们通过在硬件中实现读屏障来减少它.之前已经提出了读取障碍,但是软件读取障碍会使吞吐量降低太多,因为指针读取比写入更常见.