zgc,炙甘草汤

http://www.itjxue.com  2023-01-20 01:06  来源:未知  点击次数: 

ZGC原理与实现分析

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

最大GC停顿10ms

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

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

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

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

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

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

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

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

大部分对象标记和对象转移都是可以和应用线程并发。只会在以下阶段会发生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个阶段,即MarkRemap阶段和Relocate阶段

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

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

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

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

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

期待的标记值为100

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

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

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

来到下一次GC周期:

期待的标记值为010

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

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

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

如此反复切换。

我们知道在一些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目前有4中机制触发GC

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

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

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

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

第一次STW, 标记roots对象

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

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

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

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

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

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

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

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

zgc具体流程

zgc具体流程:

通过-Xmx10g进行设置。

-Xmx是ZGC收集器中最重要的调优选项,大大解决了程序员在JVM参数调优上的困扰。ZGC是一个并发收集器,必须要设置一个最大堆的大小,应用需要多大的堆,主要有下面几个考量:

对象的分配速率,要保证在GC的时候,堆中有足够的内存分配新对象

一般来说,给ZGC的内存越多越好,但是也不能浪费内存,所以要找到一个平衡。

Concurrent GC Threads

通过-XX:ConcGCThread = 4进行设置。

并发执行的GC线程数,如果没有设置,在JVM启动的时候会根据CPU的核数计算出一个合理的数量,默认是核数的12.5%,但是根据应用的特性,可以通过手动设置调整。

因为在并发标记和并发移动时,GC线程和应用线程是并发执行的,所以存在抢占CPU的情况,对于一些对延迟比较敏感的应用,这个并发线程数就不能设置的过大,不然会降低应用的吞吐量,并有可能增加应用的延迟,因为GC线程占用了太多的CPU,但是如果设置的太小,就有可能对象的分配速率比垃圾收集的速率来的大,最终导致应用线程停下来等GC线程完成垃圾收集,并释放内存。

一般来说,如果低延迟对应用程序很重要,那么不要这个值不要设置的过于大,理想情况下,系统的CPU利用率不应该超过70%。

Parallel GC Threads

通过-XX:ParallelGCThreads = 20

当对GC Roots进行标记和移动时,需要进行STW,这个过程会使用ParallelGCThreads个GC线程进行并行执行。

ParallelGCThreads默认为CPU核数的60%,为什么可以这么大?

因为这个时候,应用线程已经完全停下来了,所以要用尽可能多的线程完成这部分任务,这样才能让STW尽可能的短暂。

ZGC是什么机场

ZGC是

ZGC是兰州中川国际机场的IATA(国际航空运输协会)机场代码。

机场代码分三字、四字两种,在空运中以三个英文字母简写航空机场名,称“机场三字代码”或“三字码”。机场三字代码简称“三字码”,由国际航空运输协会(IATA)制定。

国际航空运输协会(IATA)对世界上的国家、城市、机场和加入国际航空运输协会的航空公司制定了统一的编码。所以兰州中川国际机场的机场代码就是ZGC。

扩展资料:

兰州中川国际机场历史沿革

兰州中川国际机场始建于1968年。

1970年7月26日,兰州中川机场首航成功,

1997年6月15日,兰州中川机场扩建工程于正式开工建设。 2001年,兰州中川机场扩建工程完工并投入使用。

2010年12月27日,兰州中川机场二期扩建工程正式开工。

2011年6月26日,兰州中川机场T2航站楼正式开工建设。

2015年1月18日,兰州中川国际机场二期扩建工程顺利竣工验收。同年2月4日,兰州中川国际机场T2开始运行。

2016年10月13日,兰州中川国际机场4000米跑道顺利完成了标志线、助航灯光、导航台站的切换,并正式开放投运,标志着兰州中川国际机场二期扩建工程全面完工。

2019年2月,国家发改委正式通过《关于甘肃兰州机场三期扩建工程项目建议书的批复》,同意实施兰州中川国际机场三期扩建工程。

参考资料来源:百度百科-机场代码

参考资料来源:百度百科-兰州中川机场

(责任编辑:IT教学网)

更多

相关微信营销文章

推荐微信营销文章