ZGC原理与实现分析

ZGC: 可扩展的低延迟的垃圾回收器

目标

支持TB级堆内存(最大4T)

最大GC停顿10ms

对吞吐量影响最大不超过15%

数据

SPECjbb 2015基准测试,128G堆内存,单次GC停顿最大1.68ms, 平均1.09ms

特性

Colored pointer

在对象的引用中借用几个bit存储额外状态标记,Load Barrier会根据这些状态标记执行不同的逻辑

Load Barrier

加载屏障:在应用线程从堆中加载对象应用后,执行的一段逻辑

跟CPU中的内存屏障(Memory barrier)完全没有关联

Single generation

目前ZGC没有分代,每次GC都会标记整个堆

Page Allocation

将堆分为 2M(small), 32M(medium), n*2M(large)三种大小的页面(Page)来管理,根据对象的大小来判断在那种页面分配

Partial compaction

在relocation阶段将Page中活的对象转移到另一个Page,并整个回收原Page。会根据一定算法选择部分Page进行整理。

Mostly Concurrent

大部分对象标记和对象转移都是可以和应用线程并发。只会在以下阶段会发生stop-the-world

1. GC开始时对root set的标记时

2. 在标记结束的时候,由于并发的原因,需要确认所有对象已完成遍历,需要进行暂停

3. 在relocate root-set 中的对象时

原理

简述

逻辑上一次ZGC分为Mark(标记)、Relocate(迁移)、Remap(重映射)三个阶段

Mark: 所有活的对象都被记录在对应Page的Livemap(活对象表,bitmap实现)中,以及对象的Reference(引用)都改成已标记(Marked0或Marked1)状态

Relocate: 根据页面中活对象占用的大小选出的一组Page,将其中中的活对象都复制到新的Page, 并在额外的forward table(转移表)中记录对象原地址和新地址对应关系

Remap: 所有Relocated的活对象的引用都重新指向了新的正确的地址

实现上,由于想要将所有引用都修正过来需要跟Mark阶段一样遍历整个对象图,所以这次的Remap会与下一次的Remark阶段合并。

所以在GC的实现上是2个阶段,即Mark&Remap阶段和Relocate阶段



向下箭头表示STW, 横向箭表示并发阶段

Colored pointer

在64位系统中,ZGC利用了对象引用的4bit(低42位:对象的实际地址)


Marked0/marked1: 判断对象是否已标记

Remapped: 判断应用是否已指向新的地址

Finalizable: 判断对象是否只能被Finalizer访问(本文分析忽略此标记)

这几个bits在不同的状态也就代表这个引用的不同颜色

为什么有2个mark标记?

每一个GC周期开始时,会交换使用的标记位,使上次GC周期中修正的已标记状态失效,所有引用都变成未标记。

GC周期1:使用mark0, 则周期结束所有引用mark标记都会成为01。

GC周期2:使用mark1, 则期待的mark标记10,所有引用都能被重新标记。

内存映射

通过Linux系统调用mmap将标记位(001,010,100)三种地址空间映射到同一地址上,使三种地址解析后都指向同一地址,Load Barrer保证返回的地址是其中一个。


GC周期

GC在每个阶段维护一个全局的唯一的期望标记,当发现引用的状态跟期望的不一致,Load barrier会修复应用的标记到期待的状态。并会根据状态的不同执行不同的逻辑。

下面分析不同阶段的实现流程

当前为Mark/Remap阶段

期待的标记值为001,此处只关注Mark操作,Remap逻辑下面说明。

当前加载的引用标记010,Load barrier会将引用的标记修正为001,然后保存回这个引用的来源对象中,这样在下次再加载相同时可以避免重复执行。同时会帮助GC进行对象标记,方式为将这个引用添加到当前线程的本地标记stack中,并发的GC线程会遍历这些引用,并递归遍历引用的对象图

当前为Relocation阶段

期待的标记值为100

GC线程会执行为relocation set执行relocate工作,将page编辑为relocating(迁移中),只迁移对象,不关注对象的引用,relocation结束后,对象的引用会指向过期的位置。

此阶段业务线程加载对象引用时,进行remap操作:先判断指向的页面状态是否为relocating, 如果是relocating, 会协助GC线程做relocate工作。并更新此引用的的标记为100,如果不是relocating,直接更新标记为100。

当Relocation阶段完成时会存在部分引用未更新,标记为001。

来到下一次GC周期:

当前为Mark/Remap阶段

期待的标记值为010

如果当前加载的引用为100,表示已完成remap,更新标记为010

如果为其他状态,则会执行rmap操作,然后更新标记为010

同时会对对象进行mark操作,前面已经说明。

如此反复切换。

Page管理

对象分配

我们知道在一些GC算法下分配对象是通过撞指针法,也即是TLAB机制来分配。在ZGC中针对不同类型的Page,有不同的分配机制。

在堆上分配对象时,是根据对象的大小选择在不同类型的Page中分配,不同Page对象的分配策略不同。

Small Page(<=256K):每个CPU会关联一个small page,线程在分配对象时,先查找线程所运行在的cpu id, 找到关联的Page,进行分配。page剩余内存不够时,会尝试在新Page分配并切换cpu绑定的page为新的page。

Medium Page(<=4M): 所有线程在同一个Page分配

Large Page:每个large对象占用一个Page, 根据对象大小先分配合适大小的Page,然后在Page中分配对象

ZGC触发时机

ZGC目前有4中机制触发GC

1. 定时触发,默认为不使用,可通过ZCollectionInterval参数配置

2. 预热触发,最多三次,在堆内存达到10%、20%、30%时触发,主要时统计GC时间,为其他GC机制使用

3. 分配速率,基于正态分布统计,计算内存99.9%可能的最大分配速率,以及此速率下内存将要耗尽的时间点,在耗尽之前触发GC(耗尽时间 - 一次GC最大持续时间 - 一次GC检测周期时间)

4. 主动触发,(默认开启,可通过ZProactive参数配置) 距上次GC堆内存增长10%,或超过5分钟时,对比距上次GC的间隔时间跟(49 * 一次GC的最大持续时间),超过则触发

简单的GC示例


第一次STW, 标记roots对象


并发标记阶段,所有活对象以及对象引用都被标记

此后会有第二次STW,确保所有对象都被标记


选择需要整理的Page集合(relocation set)


第三次STW, 转移root中的对象


当一个Page内的活对象全部转移后,此Page的内存可以立即重用。

这是个和有用的特性,relocation set中下个page的对象可以转移到这个释放的内存中,理论上在GC时只需要有一个可转移的空页就可以了。


到此,一个GC周期就结束了。



剩下的修复工作由Load Barrier以及下次GC来完成


转载请注明来源:https://www.jianshu.com/p/4e4fd0dd5d25

参考

https://www.zhihu.com/question/287945354/answer/458761494

http://dinfuehr.github.io/blog/a-first-look-into-zgc/

http://cr.openjdk.java.net/~pliden/slides/ZGC-Jfokus-2018.pdf

https://www.usenix.org/legacy/events/vee05/full_papers/p46-click.pdf

http://go.azul.com/continuously-concurrent-compacting-collector

https://www.jianshu.com/p/5f9095ccc11e

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容