高并发系统为何建议选择G1垃圾收集器,g1垃圾回收机制
00-1010序G1概述1、最大堆大小2、区域大小3、获取默认值的三种GC模式1、新一代回收2、混合回收3、全GC默认参数1、堆内存2、新一代内存回收3、混合回收垃圾在堆内流动1、对象如何进入老年(1)大对象直接进入老年(2)动态年龄判断2、高并发加速进入老年的优化。设置垃圾收集器2、设置堆大小3、元空间设置4、GC暂停时间5、新一代大小调优练习1、频繁YGC2、频繁混合GC(1)大对象(2)元空间3、全GC。
00-1010目前企业级使用的主流Java版本是8,垃圾收集器支持手动修改到G1。G1垃圾收集器是Java 11的默认设置,所以G1垃圾收集器可以长期使用。目前,垃圾收集器优化意味着对G1垃圾收集器的优化。
为了简化讨论,我们假设它针对4C/16G物理机进行了优化。
目录
00-1010G1管理的最大堆大小是64G。每个区域的大小由-xx3360g1堆大小设置,为1~32MB。默认情况下,最多可以有2048个区域,G1可以管理的最大堆内存是32MB*2048=64G。
G1垃圾收集器的最小堆内存应该是1MB*2048=2GB,低于这个内存建议使用其他垃圾收集器。
序言
区域大小为1~32MB,具体值为1MB、2MB、4MB、8MB、16MB、32MB。区域大小优化与大型对象有关,当一个对象占用该区域内存的一半以上时,将被视为大型对象。
标记为大对象将不利于垃圾回收。
00-1010检查本地JVM的当前默认值,尤其是G1垃圾收集器。
Java-XX: print flags initial ~/1 . txt
00-1010G1垃圾收集器有两种垃圾收集模式,新一代回收和混合回收,特殊情况下会切换到全GC。
00-1010新一代回收会在最大暂停时间内处理完伊甸园的所有垃圾。具体操作是将伊甸区所有幸存对象复制到幸存者区,同时清空伊甸区。
新一代回收伴随应用暂停,最长暂停时间不超过最大暂停时间。新一代回收虽然有暂停机制,但是考虑到并行回收的特点,回收逻辑比较简单,回收效率还是很高的。一般来说,新一代回收的实际耗时通常低于最大暂停时间。
新一代回收的触发时间是新创建的对象在伊甸园区域找不到足够的存储空间。
00-1010混合回收伴随着新一代回收和老年回收。在最大暂停时间内,伊甸园区的大部分垃圾和一些陈年垃圾将得到处理。
旧的回收无疑会伴随着应用暂停。回收操作很复杂。与新一代回收相比,单位时间回收的垃圾量更少,回收效率更低。一般来说,混合恢复的实际时间通常接近或等于最大暂停时间。
混合回收的触发时间由参数InitiatingHeapOccupancyPercent控制。默认值为45,这意味着当旧时代占用的空间与总堆大小之比超过这个数字时,将会触发混合回收。
默认值45%比较合理,不建议所谓的调优。旧的回收策略也是将选中区域的活体复制到空闲区域,混合回收可以随着新一代垃圾的回收清理出更大的空闲区域来存放旧区域的活体,从而保证回收过程的正常进行。
一般老年区存活的对象比较多,在内存中复制对象需要很长时间,所以混合回收效率比较低。
G1概览
满垃圾收集是所有G1垃圾收集调谐器尽力避免的情况。单线程收集垃圾,收集的对象是整个堆,不再受最长暂停时间的约束。一旦出现这种情况,就意味着应用程序的响应时间无情地变长了。
当一个应用程序不规则地进入完全GC状态时,与其让它的单线程重塑堆内存,不如采用一种冗余策略,在lo时逐个重启应用程序
00-1010参数默认值表示优化建议MaxGCPauseMillis200ms最大暂停时间G1过载不设置启动。
发式推断G1NewSizePercent5新生代最小百分比G1MaxNewSizePercent60新生代最大百分比
2、新生代内存回收
参数默认值说明优化建议ParallelGCThreads并行GC线程数,会根据CPU核数推断默认值MaxTenuringThreshold15从新生代晋升到老年代年龄阈值SurvivorRatio8Eden和一个Survivor的比例TargetSurvivorRatio50Survivor区内存使用率,增大该值会降低到老年代概率+G1EagerReclaimHumongousObjectstrue是否在YGC时回收大对象
3、混合回收
参数默认值说明优化建议G1MixedGCCountTarget8值越大,收集老年代分区越少G1OldCSetRegionThresholdPercent10表示一次最多收集10%的分区
垃圾在堆中流转
垃圾回收器调优的关键是尽可能减少Mixed GC的频率,换句话说尽可能减少垃圾流转到老年代
。GC调优便是认识垃圾在堆中的流转规律,从而对流向老年代的垃圾予以提前干涉,使之尽可能留在新生代
。
垃圾在新生代(主要指Eden区)中,垃圾回收使用YGC,回收线程与应用线程并发进行,垃圾回收对应用透明进行,假如CPU算力充足的话,应用几乎感觉不到垃圾在回收进行。
垃圾在老年代中,垃圾回收采用Mixed GC,回收线程开始工作时,应用线程阻塞,等待回收线程工作完毕有,应用线程重新被唤醒。频繁的Mixed GC对应用的吞吐量产生不良影响。
1、对象如何进入老年代
一般而言,新创建的对象会存在于新生代的Eden区,下一次垃圾回收处罚便直接回收了。如果对象比较顽强(继续被其它对象引用),那么会在Survivor区流转,每GC一次,仍然不能被垃圾回收,那么年龄加一,继续在S0和S1区流转,当年龄增长到一定的阈值,直接进入老年代。
(1)大对象直接到老年代
新创建的对象如果过大,那么不经过新生代,直接进入老年代。控制对象大小阈值有参数-XX:PretenureSizeThreshold决定,单位字节。
(2)动态年龄判断
除了对象在S0和S1区反复流转年龄变化外,垃圾回收维护另外一套独立的年龄判定规则:如果YGC后尚未被回收的垃圾超过了Survivor区的50%,那么超过的这批对象会直接进入老年代。
12G * 60% * 10% * 50% * 1024 = 737MB
动态年龄判定规则要求每次YGC尽可能的彻底,意味着每次GC的最长时间不能太短,默认200毫秒是比较合理的值。
如果预设置的最长停顿时间过短,那么每次GC后存活大量尚未被回收的垃圾,S区容量有限,不该进入老年代的垃圾快速在老年代堆积,频繁的Mixed GC不可避免。
2、高并发加速进入老年代
在高并发场景下,CPU和内存资源吃紧,负载很高,不确定的性能抖动加速垃圾进入老年代。
举例说明,DAO层查询数据库,一次完整的会话结束后,整个会话中产生的对象垃圾在Eden区应当被全部回收。由于网络波动,数据库处理能力的限制,大量会话超时。在此过程中这部分对象垃圾很可能在快速S0和S1流转中叠加年龄,或者触发动态年龄判定,直接进入老年代。
老年代内存空间不够用,触发Mixed GC,Mixed GC直接副作用是应用卡顿。
调优步骤
1、设置垃圾回收器
Java 8需要手动指定G1垃圾回收器,命令行添加-XX:+UseG1GC参数。
2、设置堆大小
设置内存堆大小有两点需要注意:初始堆大小与最大堆大小保持一致;堆大小占物理内存大小75%~80%,给系统核心服务预留必要的内存。
参数-Xmx12G
设置初始堆大小;参数-Xms12G
设置最大堆大小。
3、元空间设置
元空间是指存储静态类、静态方法、常量等特殊变量的内存区域。
参数-XX:MetaspaceSize=1G设置元空间初始大小;参数-XX:MaxMetaspaceSize=1G设置元空间最大大小。
4、GC停顿时间
GC停顿时间是指每次YGC
或者Mixed GC
的最大时间,垃圾回收器会根据用户设置的期望时间动态选择垃圾扫描的范围,如果设置时间过小,可能总有一部分垃圾不能得到回收。单位毫秒。
-XX:MaxGCPauseMillis=200
5、新生代大小
参数-XX:G1NewSizePercent设置新生代初始大小,默认为5%;参数-XX:G1MaxNewSizePercent设置新生代最大大小,默认为60%。
新生代内部细化为Eden
区和两个Survivor
,默认比例是:8:1:1
Eden: 12G * 60%* 80% = 5.76GS0: 12G * 60%* 10% = 0.72GS1: 12G * 60%* 10% = 0.72G
假设并发系统每秒创建500MB的对象,假设每次YGC根据预先设置的最长停顿时间都能够扫描到Eden Region,那么此并发系统大约每隔10秒需要进行一次YGC。
调优实践
GC垃圾回收调优是在物理硬件受限制,并且有调优的理论空间下进行的。条件允许的话,直接升级硬件配置特别是物理内存配置,能够有效降低GC频率。比如8C32G或者16C64G等。
1、频繁的YGC
当并发量较大时,频繁的YGC时必然的,单位时间类创建了更多的对象,使用完毕之后成为了垃圾。频繁的YGC有加速S区对象流向老年代的可能,尽可能保证每次YGC的实际耗时低于预设置的最长垃圾回收时间(默认200毫秒),以便能够每次都能将新生代垃圾清理完成,尽可能延缓垃圾流向老年代。
2、频繁的Mixed GC
在G1垃圾回收器中,没有所谓的Mixed GC的概念,Mixed GC类似于F·GC,不同的是Mixed GC除了回收老年代,同时也回收新生代,共同之处在于都会产生STW
。
频繁的Mixed GC
本质是大量应该在新生代回收的垃圾进入了老年代,解决思路是排查哪些哪些垃圾(对象)应该留在新生代,却流转到老年代。
(1)大对象
检查应用程序是否周期性的创建大对象,大对象的阈值由参数-XX:PretenureSizeThreshold控制。假如内存有优化空间的前提下适当调高此值,不得超过S区的一半(似乎没有这么大的对象),副作用是新生代存放对象数量相应变少,Eden区内存更快的用完,YGC相应的变频繁一些。
从业务的角度来讲,大对象产生必有其产生的原因,从这个角度优化可能性不高,垃圾回收器优化尽可能屏蔽业务层代码,毕竟对开发提要求让其不要创建大对象不现实。
(2)元空间
元空间耗尽也会引发Mixed GC
,考虑到元空间存储内容的特殊性,因元空间耗尽导致GC频率提高并没有很好的办法。单纯提高元空间大小会压缩新生代大小,新生代变小,对象流转到老年代的数量会变多,老年代内存消耗加快,同样会提高GC的频率。
因元空间耗尽引发的Mixed GC
,相对来说增加物理内存是比较优的解决方式。
3、Full GC
尽管Mixed GC
被触发时,应用会暂时停止响应(默认值是200毫秒),暂停的时间是相对可控的。
如果在进行Mixed GC
时,空闲的Region无法保存存活的对象,Mixed GC无法正常进行时,垃圾回收会切换到 G1 之外的Serial Old GC
来收集整个堆,包括新生代、老年代、元空间等。
进入Serial Old GC
垃圾回收状态,垃圾回收不再受最长回收时间约束,采用单线程进行标记、清理和压缩整理,应用可能进入假死
状态。也许重启应用,重新分配堆内存,将堆内存彻底洗牌,也许会更好。
G1垃圾回收调优的关键是不要出现Full GC,因此对于敏感的参数千万不要乱调优,否则不仅达不到理想想过,反而更糟糕。
以上就是G1垃圾回收器在并发场景调优详解的详细内容,更多关于G1垃圾回收器并发调优的资料请关注盛行IT其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。