ZGC的7种垃圾回收触发时机

王英
• 阅读 3053

ZGC中,为了实现更高的性能,尽量避免进行同步垃圾回收,也就是说尽量避免触发同步的垃圾回收的消息。ZGC中触发同步消息的场景也比较少,总体以触发异步消息为主。异步消息主要由ZDirector根据规则判断是否可以触发,在ZDirector流程图中【了解更多,可以阅读小编的另一篇文章:ZGC线程之时钟触发器和消息触发】介绍了ZDirector有4种触发规则,本文主要介绍这4种规则是如何触发的,最后,还会简要介绍其他的垃圾回收消息是如何触发的。
一、基于固定时间间隔触发
    ZDirector提供的第一个规则就是基于固定时间间隔触发垃圾回收。这个规则的目的非常简单,就是希望ZGC的垃圾回收器以固定的频率触发。在这一些场景中非常有用,例如我们的应用程序在晚上请求量比较低的情况下运行了很长时间,但是ZGC不满足其他垃圾回收器的触发条件,所以一直不会触发垃圾回收,这通常没什么问题,如果在早上某一个时间点开始请求量暴增,这可能导致内存使用也暴增,而垃圾回收器来不及回收垃圾对象,将降低应用系统的吞吐量。所以ZGC提供了基于固定时间间隔触发垃圾回收的规则。
    这个规则的实现也非常简单,就是判断前一次垃圾回收结束到当前时间是否超过时间间隔的阈值,如果超过,则触发垃圾回收,如果不满足,则直接返回。
    需要说明的是,时间间隔由一个参数ZCollectionInterval来控制,这个参数的默认值为0,表示不需要触发垃圾回收。实际工作中,可以根据场景设置该参数。
二、预热规则触发
    ZDirector提供的第二个规则是预热启动垃圾回收。为什么设计这一规则?设计这一规则的目的是当JVM刚启动时,还没有足够的数据来主动触发垃圾回收的启动,所以设置了预热规则。
    预热规则指的是JVM启动后,当发现堆空间使用率达到10%、20%和30%时,会主动地触发垃圾回收。ZGC设计前3次垃圾回收可由预热规则触发,也就是说当垃圾回收触发(无论是由预热规则,还是主动触发垃圾回收)的次数超过3次时,预热规则将不再生效。
三、根据分配速率
    ZDirector提供的第三个规则是根据分配速率来预测是否能触发垃圾回收。这一规则设计的思路是:
    1)收集数据:在程序运行时,收集过去一段时间内垃圾回收发生的次数和执行的时间、内存分配的速率MEMratio和当前空闲内存的大小MEMfree。
    2)计算:根据过去垃圾回收发生的情况预测下一次垃圾回收发生的时间TIMEgc,按照内存分配的速率预测空闲内存能支撑应用程序运行的实际时间TIMEoom,例如TIMEoom=MEMfree/MEMratio。
    3)设计规则:如当TIMEoom小于TIMEgc(垃圾回收的时间),则可以启动垃圾回收。这个规则的含义是如果从现在起到OOM发生前开始执行垃圾回收,刚好在OOM发生前完成垃圾回收的动作,从而避免OOM。在ZGC中ZDirector是周期运行的,所以在计算时还应该把OOM的时间减去采样周期的时间,采样周期记为TIMEinterval,则规则为TIMEoom<TIMEgc+TIMEinterval时触发垃圾回收。
    那么最主要的任务就变成了如何预测下一次垃圾回收时间TIMEgc和内存分配速率MEMratio(因为MEMfree是已知数据,无需额外处理)。
    我们以预测垃圾回收时间TIMEgc为例来看看如何预测。最简单也最直观的思路是,根据已经发生的垃圾回收所使用的时间来预测下一次垃圾回收可能花费的时间,那么就有了如下思路:
    1)收集过去一段时间内垃圾回收发生的次数和时间,取过去N次垃圾回收的平均时间作为下一次垃圾回收的预测时间;这一方法最为直观,但是准确度可能有待提高。
    2)收集过去一段时间内垃圾回收发生的次数和时间,建立一个逻辑回归模型,从而预测下一次垃圾回收的预测时间;这一方法虽然比第一种方法有改进,根据垃圾回收的趋势来预测下一次垃圾回收的时间,但这一方法最大的问题是逻辑回归模型太简单,实际上如果我们能提供更多的输入,比如应用程序使用内存的情况、线程数等建立动态模型,这应该是一个非常好的方法。
    3)使用衰减平均时间来预测下一次垃圾回收花费的时间。衰减平均方法实际上是第一种方法和第二种方法组合后的一种简化实现。它是一种简单的数学方法,用来计算一组数据的平均值,但是在计算平均值的时候最新的数据有更高的权重,即强调近期数据对结果的影响。在G1中预测下一次垃圾回收时间采用的就是这种方法。
    4)直接采用已经成熟的模型来预测下一次垃圾回收时间。ZGC中主要是基于正态分布来预测。
    学过概率论的同学大多知道这一概念。我们先来回顾一下正态分布。首先它是一条中间高,两端逐渐下降且完全对称的钟形曲线。正态分布也非常容易理解,指的是大多数数据应该集中在中间附近,少数异常的情况才会落在两端。
    对于垃圾回收算法中的数据:内存的消耗时间,垃圾回收的时间也应该符合这样的分布。注意,并不是说G1中的停顿预测模型不正确或者效果不好,而是说使用正态分布来做预测有更强的数学理论支撑。

四、主动触发
    ZDirector提供的第四个规则是主动触发规则,该规则是为了应用程序在吞吐量下降的情况下,当满足一定条件时,还可以执行垃圾回收。这里满足一定条件指的是:
    1)从上一次垃圾回收完成到当前时间,应用程序新增使用的内存达到堆空间的10%。
    2)从上一次垃圾回收完成到当前时间已经过去了5min,记为TIMEelapsed。
    如果这两个条件同时满足,预测垃圾回收时间为TIMEgc,定义规则:如果NUMgc * TIMEgc < TIMEelapsed,则触发垃圾回收。其中NUMgc是ZGC设计的常量,假设应用程序的吞吐率从50%下降到1%,需要触发一次垃圾回收。
    这个规则实际上是为了弥补程序吞吐率骤降且长时间不执行垃圾回收而引入的。有一个诊断参数ZProactive来控制是否开启和关闭主动规则,默认值是true,即默认打开主动触发规则。
    实际上这个规则和第一个规则(基于固定时间间隔规则)在某些场景中有一定的重复,第一个规则只强调时间间隔,本规则除了考虑时间之外还会考虑内存的增长和吞吐率下降的快慢程度。
五、阻塞内存分配请求触发
    阻塞内存分配由参数ZStallOnOutOfMemory控制,当参数ZStallOnOutOfMemory为true时进行阻塞分配,如果不能成功分配内存,则触发阻塞内存分配。
    注意:该触发请求是异步的,并非同步消息。页面阻塞分配会触发垃圾回收,直到垃圾回收完成并成功分配页面为止。因为是异步消息,所以页面阻塞分配请求需要额外的实现等待成功分配的功能,其实非常简单,可以通过一个循环来实现。
    那为什么ZGC不把阻塞内存分配实现成同步消息,而是通过异步消息加上循环的方式?
    原因在于同步消息请求的线程在发出同步消息后是通过通知等待机制完成的,通知等待机制通常会让出CPU,而页面阻塞分配采用异步消息加上循环的方式,这样的设计可以减少页面分配时因线程调度带来的额外开销。从这一点也可以看出,设计一款优秀的软件,需要从每一个细节出发,并仔细斟酌。
六、外部触发
    外部触发是指在Java代码中显式地调用System.gc()函数,在JVM执行该函数时,会触发垃圾回收。该触发请求是从用户代码主动触发的,从编程角度来看,说明程序员认为此时需要进行垃圾回收(当然首先是程序员正确使用System.gc()函数),所以ZGC把该触发规则设计为同步请求,只有在执行完垃圾回收后,才能进行后续代码的执行。
七、元数据分配触发
    元数据分配失败时,ZGC会尝试进行垃圾回收以确保元数据能正确分配。
    异步垃圾回收后会尝试是否可以分配元数据对象空间,如果不能,将尝试进行同步垃圾回收后可以分配元数据对象空间,如果还不成功,则尝试扩展元数据空间,再分配成功则返回内存空间,不成功则返回NULL。

点赞
收藏
评论区
推荐文章
从历代GC算法角度刨析ZGC
本文所有介绍仅限于HotSpot虚拟机,本文先介绍了垃圾回收的必要手段,基于这些手段讲解了历代垃圾回收算法是如何工作的,每一种算法不会讲的特别详细,只为读者从算法角度理解工作原理,从而引出ZGC,方便读者循序渐进地了解。
从原理聊JVM(三):详解现代垃圾回收器Shenandoah和ZGC | 京东云技术团队
现代的垃圾回收器为了低停顿的目标可谓将“并发”二字玩到极致,Shenandoah在G1基础上做了非常多的优化来使回收阶段并行,而ZGC直接采用了染色指针、NUMA等黑科技,目的都是为了让Java开发者可以更多的将精力放在如何使用对象让程序更好的运行,剩下的一切交给GC,我们所做的只需享受现代化GC技术带来的良好体验。
从原理聊JVM(一):染色标记和垃圾回收算法
本篇介绍了JVM中垃圾回收器相关的基础知识,后续会深入介绍CMS、G1、ZGC等不同垃圾收集器的运作流程和原理,欢迎关注。
Wesley13 Wesley13
3年前
Java工程师成神之路
一、基础篇1.1JVM1.1.1.Java内存模型,Java内存管理,Java堆和栈,垃圾回收http://www.jcp.org/en/jsr/detail?id133http://ifeve.com/jmmfaq/1.1.2.了解JVM各种参数及调优
Stella981 Stella981
3年前
JVM系列篇:7种JVM垃圾收集器特点,优劣势、及使用场景
本系列会持续更新。!(https://oscimg.oschina.net/oscnet/945dbe48630eb4284fea936b19161c0f08a.jpg)今天继续JVM的垃圾回收器详解,如果说垃圾收集算法是JVM内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。一、常见的垃圾收集器
Wesley13 Wesley13
3年前
Java虚拟机垃圾回收相关知识点全梳理(上)
一、前言笔者最近在复习JVM的知识,本着记录分享的精神,整理下学习Java虚拟机垃圾回收相关知识点,由于整个垃圾回收内容比较多,我将整理成上下两篇文章去分享,上篇我会主要分享Java虚拟机的运行时数据区域划分,垃圾回收算法。下篇文章主要分享Java虚拟机的垃圾回收器以及一些虚拟机调优建议。二、运行时数据区Java虚拟机
Stella981 Stella981
3年前
JavaScript 使用闭包保护变量 防止污染
使用JavaScript编写插件或团队协作时,可使用闭包来解决此类以下两个问题:1、定义过多全局变量,可能会造成全局变量命名冲突;2、在插件内定义变量,需要保护该变量不被轻易修改;优点:可以把局部变量驻留在内存中,可以避免使用全局变量;在调用过后不会被垃圾机制回收;缺点:避免滥用闭包,占用更多内存的缺点,用完要及时让垃圾回收器回收(fn
Stella981 Stella981
3年前
JVM架构体系与GC命令小总结
!(https://oscimg.oschina.net/oscnet/052a011b9ad19376d76daa6b6dcb82fa032.png)1.Overview2.JVM架构体系1)垃圾回收对象存活性判断垃圾回收算法垃圾回收器(回收算法的具体实现)
OpenJDK17-JVM源码阅读-ZGC-并发标记 | 京东物流技术团队
1、ZGC简介1.1介绍ZGC是一款低延迟的垃圾回收器,是Java垃圾收集技术的最前沿,理解了ZGC,那么便可以说理解了java最前沿的垃圾收集技术。从JDK11中作为试验特性推出以来,ZGC一直在不停地发展中。从JDK14开始,ZGC开始支持Window
删除消息后,卸载重装应用,删除的消息又出现了
问题原因:如果开启了“多设备消息同步”服务,卸载重装应用,会触发“消息补偿”机制,默认会拉取到补偿时间内收发过的消息,如果删除的消息是在补偿时间内收发的,也会被拉取回来。解决思路:1.在删除消息后,向会话发一条自定义消息,作为清除消息的标识。2.当卸载重装
融云IM即时通讯 融云IM即时通讯
8个月前
融云IM干货丨IM聊天室中客户端如何确保消息同步的准确性?
客户端确保消息同步的准确性主要依赖于以下几个关键技术和策略:全局唯一的消息ID生成策略:为了保证消息可以通过ID进行识别和排重,IM系统采用全局唯一的消息ID生成策略。这种策略可以确保每条消息都有一个唯一的标识符,从而在消息的发送和接收过程中避免重复。客户