zgc是个什么东东?简单说是个垃圾回收器。
一个低延迟的垃圾回收器!
多少年来,JVM中的各种垃圾回收器都在努力追求着两个目标,暂停时间足够短,同时吞吐量也要不错。为了追求二者兼具,各种垃圾回收器可谓绞尽脑汁,但还是无法同时让两个都足够好,要么暂停时间缩短了但吞吐量下降了,要么吞吐量上去了暂停时间却变长了,真的是操蛋,即使是现在最新的生产可用的G1也是,虽然他也号称是low latency,也可以指定暂停时间,但还是需要你去平衡暂停时间和吞吐量,G1可以说是非常努力了,但还是没有做到极致和傻白甜。
但事情总是发展的,前几天,jdk11的开发团队悄悄的在自己的功能列表中添加了一个叫ZGC的gc。没错,就是我们今天要侃的主角,一个集暂停与吞吐于一身的回收器,听着就是不是被吓尿了,是不是感觉以后都不用对JVM调优了,是不是以后代码可以xjb写了。
来看看它的目标:
看看这些目标!
TB级的堆随便搞!暂停时间10毫秒内!吞吐量最大下降15%!大声告诉我,吓尿没?!
好,继续。
暂停时间不会随着堆的增大而变长!不会!
总体印象
好,接下来,我们还是先对ZGC有个总体上的印象。
1、全新的垃圾回收器。“全新”指的是一点点从草稿然后搞出来,不是基于哪个来优化出来的。
2、使用了Load Barriors技术,而不是使用store Barriors。这是两种不同的技术。store barriors是hotspot里现存的好多垃圾回收器所用的技术。zgc中使用load barrior技术来跟踪堆的状态和对象的状态。
3、单代。它是一个只有一个generation的回收器。
4、Partial Compaction。也是基于部分压缩,这个和G1是一样的。
5、Region-Based GC。它有点像G1,都是基于region,但和G1不一样的是,zgc有更加灵活的region的size schema。这样我们就可以轻松的处理大对象的分配问题了。
6、Immediate Memory Reuse。zgc和G1一样,region们会被及时的清理和压缩和转移,可以让内存的复用更加的及时。
7、NUMA-aware。这是一种内存页合并的硬件技术。
8、Colored Object Pointers。
9、Concurrent。zgc一个非常重要的能力。就是并行和并发干几乎所有的事情。
比如:
以上这些统统并发(conccurent)搞!zgc团队为他们的这一项能力非常骄傲,这在open jdk的其他垃圾回收器是非常少有的。
目前的状态
1、ZGC目前仅支持Linux/x86_64。
2、性能方面目前是非常牛x的。无论是暂停时间还是吞吐量。
看看一些数字
这是评测结构跑的分数。重点看看蓝色的指标,可以看出ZGC要比Parallel和G1要更好。
再来看看暂停时间的分数:
是不是很夸张。暂停时间远低于他们最初定的目标10ms
GC阶段
这里先放个图,先有个印象,后面会有一个gc过程示例来详细说明。
Heap Regions
堆区域。也被称为:ZPages。
这和G1的region有点像,但和G1不一样的是,region的大小更加灵活和动态。zgc的region不会像G1那样在一开始就被划分为固定大小的region。
zgc的region核心亮点就是:动态。
动态表现为:
而且他有个概念叫:size groups。有三种:
Small:就是一个2MB的region。
Medium:32mb。2MB*16。
Large:N*2MB。
整个heap长这样:
Colored Pointers
是zgc的一个核心概念。你还可以叫它tag pointers,version pointers。
metadata被保存在64-bit的pointer中。目前不支持32位的平台。也不支持CompressedOops。
Virtual Address-masking可以是硬件或操作系统或软件。
先来看看在x86_64上的colored pointer的布局:
一个pointer共64bit。开始的18bit暂时没有被用到(以后有可能要用),然后是四个bit,分别表示Finalizable、Remapped、Marked1、Marked0,这是gc过程中每个对象的状态。最后42bit是用来存储对象的地址。
当是remapped时候,表示不要指向到relocation set(具体relocation set是个什么会在后面的gc示例中说到)中。
当颜色为Finalizable的时候,就只能通过Finalizer来访问到,其他的途径已无法访问。
Linux/x86_64上是Heap Multi-Mapping
下面是在x86_64上的heap中的address space中的pointer们的逻辑映射。
在Solaris/SPARC的heap映射:
Solaris/SPARC上是single heap mapping
Load Barrier
Load Barrier主要用于在对象从heap load的时候。而且只在这一个地方用到load barrier。一旦你过了load barrier并成功的拿到了对象,之后你就可以任意的使用它了,比如访问字段,调用方法等。为什么要加入load barrier呢?它的主要目的就是检查pointer是不是“bad color”(前面我们讲到colored pointers)。如果是一个bad color的pointer,那么就需要走一个慢的路径(slow path),然后采取一些措施然后让他变成good color,然后下次你在load的时候,就会走快的路径(fast path),而不需要做额外的措施了。
bad color:mark 、relocate、remap。
good color:repair、heal。
大部分的情况下的对象引用都是good color。
来看看一个例子:
具体的load barrier实现:
如果不是good color并且对象不为null,那么执行slow_path:
GC过程示例
接下来展示一下zgc中的gc过程。
开始示例之前,先说明下,本图的基本元素。含有箭头的线条我们称之为:pointer。然后每个数字表示object。每个方块表示一个region。
首先从roots开始一直往下连通,如果能够直接连通的,我们认为就是可达的,然后标记为红色。
Pause Mark Start
然后标记1为红色,表示ok。
然后标记2为红色。
然后标记4为红色。
Concurrent Mark
现在标记结束了。接下来进入的阶段是“重新分配准备阶段”:Concurrent Prepare for Relocate。
Relocation就是一个转移的过程。
标记过后,我们发现3,6,7是不同的颜色。
Concurrent Prepare for Relocate
标记过后,就需要确定哪些region中的对象被转移。可以发现含有3、6、7的两个region被列为了Relocation Set,意味着这两个region中的对象将会被relocation。
那么4、5、8要被转移到哪里呢?
接下来进入Pause Relocate Start阶段。
Pause Relocate Start
绿色表示Remapped+Relocate的过程。
当来到4的是,发现它属于Relocation Set的对象,于是把4转移到了最右边的那个全新的region中。然后在下面的Forwarding Table中做个记录。
然后进入到Concurrent Relocate阶段。把4转移了?那5和8怎么办呢?
Concurrent Relocate
这个阶段,负责5和8转移到4现在所在的那个region。
现在5已经被转移到了新region。原来3、4、5所在region已经被清理空了,可以重新被使用了。如下:
同样的做法,把8也转移到新的region里。
同样的又一个region被腾空了,可以被重新使用了。
GC Cycle Completed
好,是不是发现2和5已经无法连通了。接下来进入第二阶段的Pause Mark Start。
Pause Mark Start (Second Cycle)
Concurrent Mark (Second Cycle)
Pause Mark End (Second Cycle)
Concurrent Prepare for Relocate (Second Cycle)
可以发现Forwarding Table已被清空。
Stripe Mark
好,你也许好奇,那么多的region,zgc是怎么进行一个个进行回收的呢?上面只是展示了几个对象而已,几个region而已。
这里就要说到zgc的一个宏观的条纹标记技术:Striped Mark。光听到这名词,你也许不知道具体是怎么做的。
这就是条纹,每个条纹的颜色不同。
条纹标记法会把heap逻辑上分成若干个条纹组。然后把每个gc线程都隔离到它自己的stripe上进行gc。
现在假设有四个GC线程。然后Heap如上所示。
然后把heap分为不同颜色的条纹。
然后再抽象一层stripe分组。
不同颜色的条纹由不同的线程来处理。
但有种情况是有的GC线程提前完成了自己所在stripe的清理工作。此时它会加入到其他的stripe上继续帮助其他的gc线程继续清理其他的stripe(这个思路有点类似工作窃取算法)。
好,以上就是全部。ZGC,一个集暂停与吞吐于一身的GC,一个暂停时间控制在10毫秒以内的GC
本文分享自 ImportSource 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!