面试官:ZGC 为什么能做到低延时?

IT可乐

共 1622字,需浏览 4分钟

 ·

2021-10-28 22:34

38c1b99c6130fad5b96a5ab512c4cd0b.webp我们知道只要是编程语言,就会产生内存垃圾,如何回收这些内存垃圾?
JavaCoder 认为垃圾回收太重要了,所以要把这项任务交给编译器,让他来帮助我们完成垃圾回收;
但是C++Coder 也认为垃圾回收太重要了,掌握在自己手里才放心,所以由程序员自己来完成垃圾回收;

两种编程语言,两种不同的实现方式,也是两种处世哲学吧。

而可乐作为一个长期从事Java开发的coder,与垃圾回收确实打过不少交道,任何服务都讲究准确、快速,而Java的垃圾回收会有 STW(Stop The World)产生,简单来说就是由于垃圾回收机制,会产生停顿现象。

而GC停顿对响应时间还是有很大的影响的,为了降低GC停顿对系统可用性的影响,可以从降低单次GC时间和降低GC频率两个角度出发进行调优,包括JVM参数调优,以及更换垃圾回收器,从 CMS 到 G1垃圾回收器等等,但是效果都不太理想,直到遇到了 ZGC,在最新版的 JDK17 ,它已经是作为默认的垃圾回收器了,那么它有什么神奇的魔力呢?话不多说,大家直接往下看吧。

df79be1aee6ceee421a9dc60d2a5ee08.webp

1、官方介绍

为了保证介绍的足够官方,足够权威,我们先看看官方介绍

官方网址:https://wiki.openjdk.java.net/display/zgc/Main

ab777f7ac1de4898fc384b4488e9300a.webp

核心理念:

  • 停顿时间不超过10ms;
  • 停顿时间不会随着堆的大小,或者活跃对象的大小而增加;
  • 支持8MB~4TB级别的堆(未来支持16TB)。

怎么样?是不是很诱人?是不是很想马上采用这款垃圾收集器,那么 ZGC 为什么能做到这些呢?

2、垃圾回收优化历程

为了降低 GC 延时,我们通常有这样几种解决思路:

①、缩短单次 GC 回收时间(典型的提高硬件能力);

②、并发进行回收(CMS垃圾回收器,只能做到一部分并发);

③、只回收部分垃圾(G1垃圾回收器,打开新的大门);

④、ZGC(单独拿出来)

3、ZGC 原理

讲到这,开始正式进入主题:为什么 ZGC 能够做到低延时?

咱们看图说话:

4c225568a7e632adcaba8e2aa1b13d70.webp

低延时结论:

ZGC在标记、转移和重定位阶段几乎都是并发。

在【初始标记】、【再标记】、【初始转移】这三个阶段只有 GC 线程,这就表示这三个阶段是 STW 的。其中,初始标记和初始转移分别都只需要扫描所有GC Roots,其处理时间和GC Roots的数量成正比,一般情况耗时非常短;再标记阶段STW时间很短,最多1ms,超过1ms则再次进入并发标记阶段。即,ZGC几乎所有暂停都只依赖于GC Roots集合大小,停顿时间不会随着堆的大小或者活跃对象的大小而增加。

关键技术

ZGC通过着色指针和读屏障技术,解决了转移过程中准确访问对象的问题,实现了并发转移。

GC 线程在转移对象的过程中,假设不是 STW,这也是 G1 垃圾收集器慢的原因(G1这个阶段会 STW),那么应用线程也在不断的访问对象,假设对象转移,但对象地址没有及时更新,就会造成访问旧地址的错误。

在ZGC中,应用线程访问对象将触发“读屏障”,如果发现对象被移动了,那么“读屏障”会把读出来的指针更新到对象的新地址上,这样应用线程始终访问的都是对象的新地址。那么,JVM是如何判断对象被移动过呢?就是利用对象引用的地址,即着色指针。

关于“读屏障”和“着色指针”的概念,我这里就不做过多的描述了。

2185a08259c454cadf87e7f2705cfb1d.webp

4、ZGC 缺点

ZGC 快是快,特别是对于大堆和即时响应的系统特别有用,但是还是存在缺点的:

①、并发标记阶段是全堆标记,如果回收速度跟不上对象分配速度,会导致对象分配停顿。

②、GC线程并发导致 CPU 飙高。

怎么用大家做好取舍。

关于我

可乐是一个热爱技术的Java程序猿,公众号「IT可乐」定期分享有趣有料的精品原创文章!

e2ac5cd855f24a1d29ea2ea26ef0819c.webp

非常感谢各位人才能看到这里,原创不易,文章如果有帮助可以关注、点赞、分享或评论,这都是对我的莫大支持!

愿你我人生尽量没有遗憾的事,愿你我都能奔赴在各自想去的路上。


浏览 70
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报