jdk16 ZGC 改进
所属分类 ZGC
浏览量 936
ZGC | What's new in JDK 16
原文
https://malloc.se/blog/zgc-jdk16
通过并行线程栈扫描,GC暂停时间微秒级,平均暂停时间约为 50 微秒(0.05 毫秒),最大暂停时间约为 500 微秒(0.5 毫秒)
暂停时间不受堆、活动集和根集大小的影响。
不再有保留堆区域,在需要时进行就地移动。节约内存,同时也能保证堆在所有情况下都能成功压缩。
转发表 更有效地进行分配和初始化,缩短GC 时间,特别是在收集稀疏的大型堆时。
O(1) 的暂停时间
以恒定的时间执行,不受堆、活动集合(live-set)和根集合(root-set)的大小的影响
JDK16之前 ZGC暂停时间与根集合的大小相关
在线程运行时在堆栈里进行扫描
栈水印屏障(Stack Watermark Barrier)
JEP 376: ZGC: Concurrent Thread-Stack Processing
支持 就地移动(in-place relocation)
避免了在堆已满的情况下需要 GC 回收垃圾时产生 OutOfMemoryError
通过将可紧凑打包(densely packed)的对象从较稀疏的堆区域移动到一个或多个空的堆区域来压缩堆
需要一些空闲内存(每个大小的类型都至少要一个空的堆区域)才能开始移动过程
如果堆已满,那么就无处移动对象
JDK16 之前,ZGC 通过保留堆(heap reserve)来解决这个问题
保留堆是一组堆区域,这些区域被预留出来,不用于 Java 线程中的常规堆分配,只允许 GC 在移动对象时使用保留堆
这确保有空的堆区域可用,即使在 Java 线程眼中堆已满,也可以开始移动过程。
就地压缩堆
移动对象对象的顺序很重要,否则可能会覆盖尚未移动的对象
需要 GC 线程之间更多的协作,不利于并行处理
JDK16 开始 ZGC 同时使用这两种方法来同时获得二者的好处
不需要保留堆,同时在通常情况下保持良好的移动性能,并保证在边缘情况下总是能成功完成移动
默认情况下,只要有空的堆区域可用于移动对象,ZGC 就不会就地移动对象
如果没有空堆区域,ZGC 就会切换到就地移动
一旦空堆区域可用,ZGC 将切换为不就地移动的状态
转发表的分配和初始化
当 ZGC 移动对象时,该对象的新地址会被记录在转发表中,该表是在 Java 堆以外分配的数据结构。
每个被选为移动集(需要压缩以释放内存的堆区域集)一部分的堆区域都会得到一个与其关联的转发表
JDK16 之前,当移动集非常大的时候,转发表的分配和初始化可能会占用 GC 周期中的很大一部分时间
JDK16 ,批量分配转发表
一次性分配所有表的所需内存
避免分配开销和潜在的锁竞争,并显著地减少分配这些表所需的时间
表的初始化是另一个瓶颈
使用多个线程(而不是单个线程)并行进行初始化
上一篇
下一篇
postman上传文件
Map computeIfAbsent 实例
励志歌曲系列
字符串编辑距离 Levenstein edit distance
最简单的RPC框架实例
aerospike lua 构建有序列表