ZGC回收器到底有多变态?

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一个非常重要的能力。就是并行和并发干几乎所有的事情。

比如:

  • 1、Marking。
  • 2、Relocation和Compaction。
  • 3、Relocation Set Selection。
  • 4、Reference Processing。
  • 5、JNI WeakRefs Cleaning。
  • 6、StringTable和SymbolTable Cleaning。
  • 7、Class Unloading。

以上这些统统并发(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核心亮点就是:动态。

动态表现为:

  • 1、动态地创建和销毁。
  • 2、动态地决定region的大小。它的最小单位是2MB的一个块。然后每个region的大小就是是2MB*N就是。

而且他有个概念叫: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(importsource)

原文发表时间:2018-07-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏日常学python

爬取《The Hitchhiker’s Guide to Python!》python进阶书并制成pdf

这是日常学python的第15篇原创文章 前几篇文章我们学习了requests库和正则,还有个urllib库,我上篇文章也用了requests库来教大家去爬那些...

452170
来自专栏java一日一条

成为JavaGC专家(1)—深入浅出Java垃圾回收机制

对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC如何工作可以帮你写出更好的Java应用...

17820
来自专栏ytkah

利用excel数据透视表实现快速统计相关数据

  昨天ytkah在做数据报表时需要做一些具体统计数字:公司每天都有人申请铅笔、笔记本等一些文具用品,现在想要统计每天申请铅笔多少支、笔记本多少本,如下图所示,...

336100
来自专栏Python数据科学

Python爬虫之一个海贼迷的呐喊

海贼王已经10年了,一路陪伴了我们的点点滴滴。它热血,激情,感人,欢乐,吸引了无数男女老少的紧紧跟随。

13030
来自专栏小詹同学

爬点重口味的 。

小弟最近在学校无聊的很哪,浏览网页突然看到一张图片,对面的女孩看过来(邪恶的一笑),让人想入非非啊,一看卧槽,左边这妹子彻底赢了,这(**)这么大,还这么漂亮,...

17220
来自专栏编程

那些有趣的 Linux 命令

英文:mylinuxbook,译文:快乐的骚年, www.cnblogs.com/sukai/archive/2013/06/08/3127031.html 1...

253100
来自专栏Windows Community

Windows Community Toolkit 3.0 - CameraPreview

Windows Community Toolkit 3.0 于 2018 年 6 月 2 日 Release,同时正式更名为 Windows Community...

10910
来自专栏极客生活

python爬虫隔一段时间一乐之海子的诗

每隔一段时间(一周到一个月)拿出1到2天来做一个好玩的东西,不求回报,只为快感。 前两天刚买了一本电子书《海子的诗》,晚上读了快一半,好多诗里面都提及了麦子和...

10710
来自专栏GopherCoder

专栏:007:xpath使用及其实战

14430
来自专栏iOSDevLog

Unity 3D 开发《王者荣耀》:英雄移动地图英雄

28630

扫码关注云+社区

领取腾讯云代金券