ZGC 是 Oracle 内部研发的一款新的垃圾回收器,最大的宣传点是低延迟(Low Latency)。根据近期的消息,该项目将会托管给 OpenJDK,由后者开发完善。
ZGC 特性一览
ZGC 的设计目标
- TB 级别的堆内存管理;
- 最大
GC Pause
不高于 10ms; - 最大的吞吐率(
Throughput
)损耗不高于 **15%**;
关键点:GC Pause
不会随着 堆大小的增加 而增大。
ZGC 中关键技术
- 加载屏障(
Load barriers
)技术; - 有色对象指针(
Colored pointers
); - 单一分代内存管理(这一点很有意思);
- 基于区域的内存管理;
- 部分内存压缩;
- 即时内存复用。
并行化处理阶段
- 标记(
Marking
); - 重定位(
Relocation
)/压缩(Compaction
); - 重新分配集的选择(
Relocation set selection
); - 引用处理(
Reference processing
); - 弱引用的清理(
WeakRefs Cleaning
); - 字符串常量池(
String Table
)和符号表(Symbol Table
)的清理; - 类卸载(
Class unloading
)。
ZGC 垃圾回收过程
ZGC Phase
ZGC 的垃圾回收算法和传统的 Stop-The-World
式的垃圾回收算法不太一样,后者的标记阶段和内存压缩阶段会使得应用线程挂起。ZGC 和 C4(Continuously Concurrent Compacting Collector)
)算法 比较类似,垃圾回收过程主要分为以下三个阶段:
- 标记(Marking) — 找到活动对象;
- 重定位(Relocation) — 将存活对象移动到一起,以便可以释放较大的连续空间,这个阶段也可称为“压缩(
Compaction
)”; - 重映射(Remapping) — 更新被移动的对象的引用。
一次完整的 ZGC 回收周期分为以下几个阶段(Phase):
Pause Mark Start
:标记根对象;Concurrent Mark
:并发标记阶段;Concurrent Relocate
:并发重定位;- 活动对象被移动到了一个新的
Heap Region
B-region 中,之前旧对象所在的Heap Region
A-region 即可复用;如果 B-region 中对象之间的引用关系将会在这一阶段被更新; - 在重定位过程中,新旧对象的映射关系(同一对象在不同
Region
中的映射关系)被记录在了Forwarding Tables
中。
- 活动对象被移动到了一个新的
Pause Mark Start
:这个阶段实际上已经进入了新的ZGC Cycle
,同样也是标记根对象;Concurrent Remap
:并发重映射。 这个阶段除了标记根对象直接引用的对象外,还会根据上个ZGC Cycle
中生成的Forwarding Tables
更新跨Heap Region
的引用;Concurrent Relocate
……
从上面的垃圾回收过程可以看到,正是因为 ZGC 回收过程中各个 Phase 的并发性,才使得 GC Pause
不受垃圾回收周期内堆上活动数据数量和需要跟踪与更新的引用数量的影响,将暂停时间保持在较低的水平。
ZGC 的垃圾回收各阶段也不都是并发执行的,在 Pause Mark Start
阶段进行根对象扫描(Root Scanning)时会出现短暂的暂停。
ZGC 回收效率
Oracle 提供了 ZGC、GC、Parallel垃圾回收器的垃圾回收效果对比,测试平台配置:16 cores,堆大小设置为128G。测试下过如下:
可以看到,在大堆的垃圾回收效率上,ZGC一骑绝尘。但是20G以下的堆回收测试结果,目前还没有具体数据。
ZGC 总结
ZGC 在内存整理和引用更新上采取了不同的策略,给垃圾回收过程带来了巨大的性能提升。内存整理和引用更新都是并发的,也是交替进行的(其他的垃圾回收算法在更新引用时需要所有的线程到达 safe-point
)。但与此同时,我们也应该看到,并发带来的 GC 吞吐率的下降也是不可忽视的。
当响应时间比吞吐量占有更高的优先级时,ZGC 是个不错的选择。而对那些不能接受长时间暂停的应用程序来说,ZGC 是个理想的选择。而对于那些只是在后台进行密集计算的应用程序,G1 或者 Parallel 垃圾回收器可能具有更好的垃圾回收性能。
附上 ZGC 的介绍 PPT:The Z Garbage Collector: Low Latency GC for OpenJDK。