Zing C4垃圾回收器

发布时间:2024-05-31 14:25:00

阅读量 : 90

Azul Systems公司的C4(Continuously Concurrent Compacting Collector)算法,使用独特的方法来实现低延迟的分代式垃圾回收。





Zing GC工作原理


相比于大多数垃圾回收器,C4的不同之处在于它认为垃圾回收并不是什么坏事(即应用程序产生垃圾很正常),而压缩是不可避免的。在设计之初,C4就是要牺牲各种动态内存管理的需求,以满足需要长时间运行的服务器端应用程序的需求。

C4算法将释放内存的过程从应用程序行为和内存分配速率中分离出来,并加以区分。这样就实现了并发运行,即应用程序可以持续运行,而不必等待垃圾回收的完成。其中的并发性是关键所在,正是由于并发性的存在才可以使暂停时间不受垃圾回收周期内堆上活动数据数量和需要跟踪与更新的引用数量的影响,将暂停时间保持在较低的水平。

大多数垃圾回收器在工作周期内都包含了stop-the-world式的压缩过程,这就是说应用程序的暂停时间会随活动数据总量和堆中对象间引用的复杂度的上升而增加。使用C4算法的垃圾回收器可以并发的执行压缩操作,即压缩与应用程序线程同时工作,从而解决了影响JVM伸缩性的最大难题。




C4算法的3个阶段
1)标记(Marking) — 找到活动对象


(2)重定位(Relocation) — 将存活对象移动到一起,以便可以释放较大的连续空间,这个阶段也可称为“压缩(compaction)”
      (3)重映射(Remapping) — 更新被移动的对象的引用。

0217cd61e1b9d2c955a971a4b05742e4.png



C4算法中的标记阶段


在C4算法中,标记阶段(marking phase)使用了并发标记(concurrent marking)和引用跟踪(reference-tracing)的方法来标记活动对象,这是C4算法与其他并发标记器的工作方式相同的地方。不同之处在于并发标记阶段中,如果应用程序线程修改未标记的对象,那么该对象会被放到一个队列中,以备遍历。这就保证了该对象最终会被标记,也因为如此,C4垃圾回收器或另一个应用程序线程不会重复遍历该对象。这样就节省了标记时间,消除了递归重标记(recursive remark)的风险。

C4算法是基于LVB(load value barrier)实现的,LVB具有自愈能力,可以使应用程序线程迅速查明某个引用是否已经被标记过了。如果这个引用没有被标记过,那么应用程序会将其添加到GC队列中。一旦该引用被放入到队列中,它就不会再被重标记了。应用程序线程可以继续做它自己的事。

在C4算法中,并没有重标记(re-marking)这个阶段,在第一次便利整个堆时就会将所有可达对象做标记。因为运行时不需要做重标记,也就不会陷入无限循环的重标记陷阱中,由此而降低了应用程序因无法分配到内存而抛出OOM错误的风险。




C4算法中的重定位 —— 应用程序线程与GC的协作


C4算法中,重定位阶段(reloacation phase)是由GC线程和应用程序线程以协作的方式,并发完成的。这是因为GC线程和应用程序线程会同时工作,而且无论哪个线程先访问将被移动的对象,都会以协作的方式帮助完成该对象的移动任务。因此,应用程序线程可以继续执行自己的任务,而不必等待整个垃圾回收周期的完成。


在C4算法中并没有清理阶段(sweep phase)。在指向被移动的对象的引用都更新为指向新的位置之前,from页中的虚拟地址空间必须被完整保留。所以C4算法的实现保证了,在所有指向这个页的引用处于稳定状态前,所有的虚拟地址空间都会被锁定。然后,算法会立即回收物理内存页。很明显,无需执行stop-the-world式的移动对象是有很大好处的。由于在重定位阶段,所有活动对象都是并发移动的,因此它们可以被更有效率的放入到相邻的地址中,并且可以充分的压缩。通过并发执行重定位操作,堆被压缩为连续空间,也无需挂起所有的应用程序线程。





C4算法中的重映射
在重定位阶段,某些指向被移动的对象的引用会自动更新。但是,在重定位阶段,那些指向了被移动的对象的引用并没有更新,仍然指向原处,所以它们需要在后续完成更新操作。C4算法中的重映射阶段(re-mapping phase)负责完成对那些活动对象已经移出,但仍指向那些的引用进行更新。协作式的重映射保证了引用只会被更新一次,该引用下的子引用也都可以指向正确的新地址。



返回顶部