G1原理—8.如何优化G1中的YGC

news/2025/1/15 22:02:25/文章来源:https://www.cnblogs.com/mjunz/p/18673797

大纲

1.5千QPS的数据报表系统发生性能抖动的优化(停顿时间太小导致新生代上不去)

2.由于产生大量大对象导致系统吞吐量降低的优化(大对象太多频繁Mixed GC)

3.YGC其他相关参数优化之TLAB参数优化

4.YGC其他相关参数优化之RSet、PLAB和大对象的处理优化

 

1.5千QPS的数据报表系统发生性能抖动的优化(停顿时间太小导致新生代上不去)

(1)一些核心参数介绍

(2)一套线上环境的参数设置

(3)停顿时间太小导致新生代不能扩展分区

(4)问题总结

(5)如何解决

 

(1)一些核心参数介绍

 -Xms/InitialHeapSize,初始堆大小   -Xmx/MaxHeapSize,最大堆大小-Xss,每个线程的堆栈大小   -XX:NewRatio,年轻代(包括Eden和两个Survivor区)与年老代的比值,使用G1时一般此参数不设置,由G1来动态的调整,逐渐调整至最优值-XX:SurvivorRatio,Eden区与Survivor区的大小比值,默认是8      -XX:PretenureSizeThreshold,大对象晋升老年代阈值,默认Region的一半      -XX:MaxTenuringThreshold,新生代晋升老年代年龄阈值,默认是15;晋升到老年代对象的年龄,每个对象在坚持过一次YGC后,年龄就增加1,当超过这个参数值时,就进入老年代-XX:MaxGCPauseMillis,垃圾回收的最长时间(最大暂停时间),默认是200ms;设置GC最大的停顿时间,G1会尽量达到此期望值,如果GC时间超长,那么会逐渐减少GC时回收的区域,以此来靠近此阈值;-XX:InitiatingHeapOccupancyPercent,启动Mixed GC并发标记时的老年代以及即将分配的对象的总内存占用堆内存百分比,默认是45   -XX:G1HeapRegionSize,G1堆内存区块大小,(Xms + Xmx ) /2 / 2048, 不大于32M,不小于1M,且为2的幂;     -XX:GCTimeRatio,GC时间占运行时间的比例,G1默认为9;GC时间的计算公式为1/(1+9) = 10%-XX:G1HeapWastePercent,触发Mixed GC的可回收空间百分比,默认是5%;在并发标记之后,我们可以知道old gen regions中有多少空间要被回收,在每次YGC之后和再次发生Mixed GC之前,会检查垃圾占比是否达到此参数,只有达到了,下次才会发生Mixed GC-XX:G1MixedGCLiveThresholdPercent,MixGC的Region中存活对象占比,默认是85%;只有小于此参数,才会被选入CSet(新生代会全部被选取)-XX:G1MixedGCCountTarget,一次并发标记之后,最多执行Mixed GC的次数,默认是8-XX:G1NewSizePercent,新生代占堆的最小比例,默认是5%-XX:G1MaxNewSizePercent,新生代占堆的最大比例,默认是60%-XX:G1OldCSetRegionThresholdPercent,Mixed GC每次回收Region的数量,默认是10%;一次Mixed GC中能被选入CSet的最多老年代Region数量比例-XX:ParallelGCThreads,STW期间,并行GC线程数-XX:ConcGCThreads,并发标记阶段,并行执行的线程数,默认是XX:ParallelGCThreads/4 

(2)一套线上环境的参数设置

 -XX:InitialHeapSize=20G -XX:MaxHeapSize=20G -Xss1M -XX:+UseG1GC -XX:SurvivorRatio=8 -XX:MaxGCPauseMillis=20 -XX:G1HeapRegionSize=4M -XX:MaxTenuringThreshold=15 -XX:InitiatingHeapOccupancyPercent=45

注意-XX:MaxTenuringThreshold最大只能是15,因为在底层这个年龄值是用了一个4位的2进制来存储的。

 

这一套参数,是一套非常常规的参数。对于一般大内存多核心的机器来说,并发不大一般都没什么性能问题。但也不是说这样的一组参数没有任何问题,可参考如下案例。

 

(3)停顿时间太小导致新生代不能扩展分区

案例的业务背景:一个提供订单数据分析的业务系统。数据报表系统的配置:16核32G,给报表系统的堆内存大小:20G。一般来说,4核8G的机器可以扛1500+QPS。这套系统因为查询数据量大、查询QPS较高,总体的QPS在8K左右。因为报表系统也是集群化部署,单台也就3K-5K之间的QPS,所以整体的性能是完全够用的。

 

这个系统的职责就是,前置服务是一个订单查询服务 + 一个大盘系统。有大量用户会使用订单查询系统,并根据一些条件来发起一些查询请求。这些查询请求会通过RPC调用这个数据查询服务来查询一套数据报表。但请求相对均衡,对这个系统产生的请求QPS在4K-6K之间(高峰期),大盘系统一般是一些商家在平台的特殊活动时期或交易窗口会开启。总用户量200W,用户量大概在20W左右,日活1W-2W(商家打开大盘)。平常对报表系统的压力,也就是3000QPS的水平,如下图示:

另外数据大盘系统还有一些自动刷新页面,每隔5秒更新一下页面最新的交易数据。这种页面一般都是在交易窗口期,或者是特殊时间段才会开启,类似于秒杀场景的时候做的交易数据监控。

订单数据分析系统的特点:QPS高、查询数据量大、数据会快速成为垃圾数据。这一套数据分析系统,在正常情况下没什么问题,运行的也一直很稳定。

 

直到有一次特殊的交易窗口,因为这次交易窗口涉及到的商家比较多,活动也比较多,达到了5w日活。打开大盘的人数大大增加,导致产生了8K+的QPS,订单查询的QPS也接近了8000左右。虽然数据报表系统是集群化部署,单台服务分下来的请求量大概在6K+。正常来说,我们服务器的配置已经算不错了,6KQPS还没有达到极限。但不知为什么在数据报表系统运行一段时间后,就会出现一次性能抖动。出现接口查询超时问题,抖动后就会恢复正常,过一段时间又发生抖动。

这个现象虽然不会影响系统使用,最多刷新一次就可以了,但用户体验差,于是不得不着手排查原因。

 

首先登录了服务器,查看了参数配置,具体的参数配置大概就是开头的那一套参数:

 -XX:InitialHeapSize=20G -XX:MaxHeapSize=20G -Xss1M -XX:+UseG1GC -XX:SurvivorRatio=8 -XX:MaxGCPauseMillis=20 -XX:G1HeapRegionSize=4M -XX:MaxTenuringThreshold=15 -XX:InitiatingHeapOccupancyPercent=45

从参数上来看,暂时没有发现什么问题,接着打开拉下来的GC日志。通过日志发现,虽然给堆内存20G,但Eden区的大小始终是1G~2G。Eden区的总大小在系统运行了很久之后爬到了2G,无法继续往上增加。

 

而G1本身是一个自动调整新生代区域的回收器,最小内存5% * 20 = 1G。而我们观察的日志中,最大也才给到2G,也就是10%的空间。然后发现很快就会触发一次Mixed GC的过程,几乎每隔几次YGC然后就发生一次Mixed GC。并且每次Mixed GC的分批次垃圾回收的这个过程的次数很多,默认8次。几乎每次Mixed GC混合回收,最终执行的分批次回收都接近8次。每次Mixed GC过程结束后,就会空闲出大量的空间。很显然这个现像是不正常的。

 

本来以为是参数配置的问题,但是查看参数后,没有发现调整新生代最大空间的这个参数设置。所以一定不是手动配置参数导致的问题,而是G1的自动调整出了问题。除了新生代的5% -60%的比例可自动调整新生代大小外,还有什么因素?

 

还有一个因素就是停顿预测模型。停顿预测模型 + YGC的时间,是G1动态调整新生代大小的一个依据。预测能够回收的Region的个数是多少—回收能力。根据回收能力,结合YGC的时间 + 停顿时间,就能得到新生代的大小。

 

假如YGC需要的时间比较久,比如新生代占用了10G内存,每次回收需要的时间大概是在200ms+。此时无法满足停顿时间,只能调小新生代的总大小来尽量满足停顿时间。

 

所以即使新生代需要扩展,在发生YGC时,结合停顿时间和历史GC数据,就会判定无法满足停顿时间。于是在YGC结束后,会调整Region个数到一个合理范围。这个Region个数不会增大很多,但会达到预测模型中的极限值。然后这个Region个数就会一直在这个附近徘徊。

 

比如这个案例的情况:从5%上涨到10%时,就一直保持在10%上下浮动。YGC后,新生代Region数量保持在G1认为的一个合理区间。因此新生代的可用内存始终上不去,从而导致QPS高时就会有大量的短周期对象进入老年代,从而导致Mixed GC经常发生。从日志中发现Mixed GC后堆内存会出现空闲情况也可以看出来:其实是有大量对象晋升到老年代,而且这些对象大多数还都是垃圾对象。

(4)问题总结

新生代内存比例始终上不去,导致老年代快速被填满达到45%从而触发Mixed GC,最终导致频繁触发Mixed GC。由于Mixed GC时间较长,包括标记、预清理、选择CSet、最终清理,最终导致系统性能抖动。

 

(5)如何解决

核心的思路是避免大量短周期存活对象进入老年代,那么应该如何调优呢?

一.调大新生代初始比例是否可行?比如直接把最小值从5%调整到20%;

二.预测模型相关参数?比如设置一个冷门参数,衰减平均差的衰减因子;

三.调整一下停顿时间?调大了会影响响应吗?20ms有必要调大吗?

 

一.第一个思路—调大新生代比例(不可取)

直接调整新生代的比例,比如初始比例直接调整到20%。然后新生代的Region数量直接就从20%开始了,这样就能解决该问题了。

 -XX:InitialHeapSize=20G -XX:MaxHeapSize=20G -Xss1M -XX:+UseG1GC -XX:SurvivorRatio=8-XX:G1NewSizePercent=20  -XX:MaxGCPauseMillis=20 -XX:G1HeapRegionSize=4M -XX:MaxTenuringThreshold=15 -XX:InitiatingHeapOccupancyPercent=45

这种方式看似还可以,但实际上并不可取,因为这个值只适合在这种特定的时间节点里使用。如果QPS再继续增大,那该怎么办?继续提高这个值到60%吗?到最后需要做的可能就是把新生代的最小值定死在一个比较高的值。也就是到最后做的就是直接定死到60%,最大值和最小值一样。很显然这种方式虽然能暂时解决问题,但无法从根本上解决问题,所以这种方式不可取。

 

二.第二种思路—调整停顿时间(可取)

由于G1根据停顿时间来预测能回收多少垃圾,以调整新生代Region数量。所以停顿时间的长短,会从根本上影响对新生代的分区。如果停顿时间太短,一定会造成每次回收时,回收不了太多垃圾。而新生代的垃圾回收,只能通过控制新生代的Region数来保证停顿时间。所以可以尝试直接调整这个停顿时间。

 -XX:InitialHeapSize=20G -XX:MaxHeapSize=20G -Xss1M -XX:+UseG1GC -XX:SurvivorRatio=8 -XX:MaxGCPauseMillis=20 -XX:G1HeapRegionSize=4M -XX:MaxTenuringThreshold=15 -XX:InitiatingHeapOccupancyPercent=45

事实上当时在线上也是这么去做的,因为一开始这个20ms停顿预测时间是考虑到,反正G1能控制停顿时间。所以不希望让接口停顿的时间过长,就简单定了一个特别小的值20ms。

 

经过重新分析后,最终把停顿时间设定在了300ms。因为报表系统的查询,其实对响应时间的要求没有那么高。并且300ms这个停顿,偶尔发生一次,也不会导致接口的超时。

 --XX:InitialHeapSize=20G -XX:MaxHeapSize=20G -Xss1M -XX:+UseG1GC -XX:SurvivorRatio=8 -XX:MaxGCPauseMillis=300 -XX:G1HeapRegionSize=4M -XX:MaxTenuringThreshold=15 -XX:InitiatingHeapOccupancyPercent=45

参数调整以后,经过一段时间的运行,以及对GC日志的观察。发现Eden区的数量会随着系统运行不断变大,最终稳定在合理的40%。不管是平时还是高峰期(开启了交易窗口)都没有出现抖动现像了。

 

(6)总结

系统发生了性能抖动,主要是因为新生代区域过小,导致大量对象进入老年代并快速成为垃圾对象。

 

优化思路:因为设置的停顿时间不合理导致新生代的大小不合理,从而导致大量对象进入老年代,所以最终的优化手段是调整停顿时间。

 

由此可见,即使是G1这种非常灵活的回收器,在参数设置上也要慎重。尤其是停顿时间,不一定是停顿时间越小越好。

 

2.由于产生大量大对象导致系统吞吐量降低的优化(大对象太多频繁Mixed GC)

(1)案例场景介绍

(2)问题原因分析

(3)问题总结

(4)解决思路

(5)总结

 

(1)案例场景介绍

本次问题发生的场景是在一次需求上线后,该需求是在订单数据分析系统上添加一个功能。这个功能就是简单的数据对比页面,比如价格环比、价格波动、订单量增涨率、增涨环比、平均价格、平均价格环比、中位数、离散分布图等。

 

有过数据大盘开发经历都知道,这些环比页面和简单数据查询不太一样。

一.数据查询多数还是按照某个周期,或者是某几个条件去查。可通过分页、分日期维度、时间维度来保证每次查询的数据量不会太大。即使是实时监控页面,要展示的数据量也不多,主要的压力来源是QPS。

 

二.而环比这种操作,需要的是大量历史数据的抽取、计算和对比的。要么就是提前计算好一些数据,然后直接做展示。把最终的结果展示到页面中,这种页面,对内存使用的压力会比较大。

 

所以在增加这一个页面后,一开始用的人比较少,每天只有几百次请求。随着系统运行,该页面因为能非常全面反映出一段时间的交易情况。于是请求量就开始逐步上升,最终达到高峰期单台服务每秒几百QPS。

此时,开始有商户反应:有时系统页面刷新要好久才能刷新出来,有时候甚至出现报错,重新刷新才能刷新出数据。这个问题的现象和前面的现象类似。

 

经过观察GC日志,发现Eden区大小正常,但Mixed GC又开始非常频繁,并且新生代区域的对象增长速度并不快,反而是老年代增长速度非常快。

 

所以直接导致的结果就是YGC频繁出现Initial Mark,也就是MixedGC的初始标记阶段。然后出现大量的Mixed GC,最终导致系统的整体QPS下降非常多。

 

QPS下降的直观表现就是:在添加新页面前的单台服务器的QPS可以达到6K。添加了这个页面后,平常问题不大。一到月中和月末就会有大量的商家打开这个环比页面,从而导致QPS骤降至单台3K左右。于是就有用户反馈系统反应慢,偶尔出现超时的现象。

 

这个现象一开始也尝试修改了一些参数,比如调大停顿时间,包括增大堆内存等。但最终的结果是运行一段时间后,依然会出现上面现象,没有解决问题。

 

(2)问题原因分析

频繁发生Mixed GC,导致系统QPS下降,并造成大量请求超时,产生问题的原因就是频繁Mixed GC。

 

那么频繁Mixed GC的原因又是什么呢?除了大量的短周期对象进入老年代外,有没有其他的原因导致大量的对象进入老年代?

 

在这个案例里面,就存在这样的一个原因。就是在进行报表分析时,由于处理的数据比较多,一次取出来很多数据。导致存储数据的对象直接进行大对象分配,从而导致老年代占比急剧上升。虽然大对象的分配有专门的分区,但它占用的空间是算在老年代空间里的。

 

正是这个原因才导致了系统经常进入Mixed GC。虽然Mixed GC也会按照满足停顿时间进行,但是频繁发生Mixed GC就导致经常要停顿。导致QPS会被拖的比较慢,因为需要大量是STW去处理GC,并且Mixed GC的回收阶段又会持续很多次(最多8次)。

 

同时,因为是大对象分配,所以容易出现加锁分配对象的情况,导致这个分配过程的速度也不如对象直接通过TLAB分配的速度快。

 

当然上面是最终总结出来的结论,当时分析的过程其实还是很曲折的。因为最开始调整停顿时间、堆内存大小等参数没效果。然后又打开了打印Region使用详情的参数,以及开启打印TLAB的日志。最后通过日志发现大量的Region都被标上HUMS类型,才确定这个原因。TLAB日志里会有慢速分配的数据,以及一个线程有多少次慢速分配数据。

 

开启打印TLAB日志的参数如下:

 -XX:+PrintTLAB -XX:+UnlockDiagnosticVMOptions -XX:+G1PrintRegionLivenessInfo

(3)问题总结

由于对象过大,以及出现大量大对象的分配请求,从而拖慢了环比页面。又因大量大对象分配导致Mixed GC频繁触发,导致系统总吞吐量下降。

 

(4)解决思路

核心思路是:避免大对象分配导致大量短周期的对象进入老年代。

 

那么应该通过怎样的调整来解决这个问题?大对象的判定规则是什么?能否通过调整TLAB增大TLAB分配对象的次数占总对象分配次数比例?

 

一.调整Region大小

对象大小达到一个Region大小的一半时,就会进行大对象分配,所以第一个思路就是把Region大小调大。

 

那么调大的基准是什么呢?调到多大才合适呢?这个就要根据环比页面的功能,看看所分配的对象到底有多大。如果一次性查出10000条数据,就会导致一个List非常大,此时可能就需要进行大对象的分配了。所以要对系统进行分析:List有没有过大、普通的对象有没有过大。

 

4M的Region是当前的Region大小。经过分析,发现批量查询程序会设置最大查2000条数据,然后分批次查。根据计算,一批数据最大的占用空间为6M,因此可把Region设置成16M。

 

把Region设置成16M后再进行测试,发现很少出现请求超时了。这样就基本上避免了直接进入大对象分配,解决了频繁Mixed GC的问题。

 

二.调整TLAB大小

但是还是会有一个并不影响系统使用的小问题。就是压测时发现:刚开始一段时间QPS上不去,会有一个爬升的过程。过了一段时间,QPS才会稳步上升到一个比较高的水准。

 

考虑到对象分配是优先进行TLAB分配,所以把TLAB的相关内容也打开了。发现TLAB的refill次数非常多,且在开始一段时间的slow分配次数也非常多,很明显这是因为没有进入TLAB分配。

 

所以经过一段时间的调试,最终把TLAB的初始大小设置到了1M。这样的设置能够直接让系统在启动初期就能达到一个比较高的QPS,即大量的普通查询请求都能直接进入TLAB分配,且允许TLAB自动调整。TLAB的大小一般都是4K或8K,所以要基于实际的系统去调整。

 

在重新测试后,发现系统到达最高QPS的速度明显快了很多。基本上启动后就可成功达到最高QPS,且能持续很长时间稳定这个QPS。

 

注意:在调整TLAB时,最好不要指定TLABSize,因为它相当于直接指定TLAB的大小,不允许系统自动调整。如果直接设置了这个值,G1就无法在内存碎片和分配效率直接找平衡点。另外设置了最小值时,不要关闭ResizeTLAB,否则也无法实现自动调整。所以只需要设置一下MinTLABSize=1M即可。

 

TLAB本身不是G1的专属,是JVM本身就有的一个对象分配的优化。G1只是根据Region分区的这个特点,做了一下自己的适配。

 

至此这个系统参数基本上就调优完毕了,调优后的参数如下:

 -XX:InitialHeapSize=20G -XX:MaxHeapSize=20G -Xss1M -XX:MinTLABSize=1M -XX:+UseG1GC -XX:SurvivorRatio=8 -XX:MaxGCPauseMillis=300 -XX:G1HeapRegionSize=16M -XX:MaxTenuringThreshold=15 -XX:InitiatingHeapOccupancyPercent=45

(5)总结

一.RegionSize要设置合理,避免出现大量的短周期对象进入大对象分配

二.大量请求不进入TLAB分配会导致QPS下降,所以要调整TLAB大小

 

由于默认情况下G1会慢慢调整TLAB大小,所以系统一开始可能会出现一段时间的性能爬坡期。因此可以根据系统情况,设置一个稍微大一点的TLAB初始值-XX:MinTLABSize。

 

3.YGC其他相关参数优化之TLAB参数优化

(1)-XX:+UseTLAB

(2)-XX:+ResizeTLAB

(3)-XX:TLABSize

(4)-XX:MinTLABSize = 64

(5)-XX:TLABWasteTargetPercent = 1

(6)-XX:TLABRefillWasteFraction

(7)-XX:TLABWasteIncreament

(8)-XX:GCLockerRetryAllocationCount

 

不难发现YGC容易出现性能问题的点,主要就是停顿时间和Region大小。基本上这两个参数设置合理后,很少会出现比较大的性能问题。

 

此外,在对象分配效率上也有一定的优化空间。比如调大Region大小和调大TLAB,都是为了提升分配对象的效率。

 

而针对对象分配,最重要的就是TLAB相关的参数,接下来介绍对TLAB相关参数进行优化的一些思路。

 

注意:TLAB并不是G1的专属,而是JVM本身就有的功能,只不过G1结合Region进行了一些适配。

 

(1)-XX:+UseTLAB

这个参数表示是否开启TLAB,默认情况下为true,我们一般不是特殊情况不要关闭这个选项。

 

(2)-XX:+ResizeTLAB

表示是否允许TLAB大小动态调整,G1会动态调整TLAB大小,会基于历史信息(每次分配大小、有多少线程参与对象分配等)进行调整。所以采取动态调整的模式,会让G1的性能更好。

 

测试发现,在不开启ResizeTLAB的情况下:性能从少量线程到多线程始终都是弱于开启的情况。并且不开启UseTLAB时,性能会非常差。

 

(3)-XX:TLABSize

这个参数会设置TLAB的值(设置后会固定),并且不能动态调整。如果直接设置这个参数,会导致ResizeTLAB被禁用,可能导致性能下降。

 

(4)-XX:MinTLABSize = 64

表示设置TLAB的最小值;由于前面案例的那个系统是大数据分析系统,其对象比较大,所以设置了一个比较大的TLAB值。

 

在实际生产中,这个值需要经过一定的观测才能设置得比较合理。合理的TLAB最小值可让系统更快进入内存碎片与分配效率的平衡期,并且在一定程度上能提升对象分配的效率。

 

正常来说,设置的值不要太过于奇特,可以设置成4、8、32这样的值。一般来说设置64K作为初始值,就是一个比较合理的值。至于为什么是64K,这个最好结合系统情况去进行分析。

 

(5)-XX:TLABWasteTargetPercent = 1

这个参数表示TLAB可占用的Eden空间的百分比,默认是1%的Eden空间。增大这个值,可以分配更大的TLAB给线程使用。如果在实际系统运行的过程中线程数量比较多,那么可以调大这个参数。

 

前面的案例中,因为是16核的机器,系统的压力虽然比较大,由于是大数据系统,线程数量相对来说会少一点,处理时长会长一点。所以调整这个比例的效果,不如调整MinTLABSize。

 

对于正常QPS压力比较大、线程数较多的系统,可以考虑调大这个参数,这样就可以让每个线程的TLAB不至于太小。

 

(6)-XX:TLABRefillWasteFraction

指的是TLAB中浪费空间和TLAB块的比例,默认值64,即1/64。可以通过提高TLAB分配的比例来提升对象的分配效率。如果过分追求分配效率,则有可能会导致内存碎片比较大。因为可能会产生大量浪费的内存,这些浪费的内存会被dummy对象填充。

 

如果要调整此参数,需要观察TLAB日志中的waste中的slow和fast的值。如果这两个值非常大,就说明内存浪费严重,需要适当减少该值。

 

(7)-XX:TLABWasteIncreament

指的是动态增加浪费空间的字节数,默认值是4。即每次动态增加的时候都增加4字节的浪费空间,一般不需要设置这个值。

 

(8)-XX:GCLockerRetryAllocationCount

这个参数代表了分配失败的次数阈值。如果超过了这个阈值后,就会直接分配失败,默认值为2。这个值最好不要调整,因为分配2次还是失败的话,基本上说明普通的YGC和Mixed GC已无法清理出足够的空间了。调大该数字可能导致多次无效GC,造成停顿的同时还不能真正解决问题。

 

4.YGC其他相关参数优化之RSet、PLAB和大对象的处理优化

(1)-XX:ParallelGCThreads

(2)-XX:G1RsetScanBlockSize

(3)-XX:TargetSurvivorRatio

(4)-XX:ParGCArrayScanChunk

(5)-XX:+ResizePLAB

(6)-XX:YoungPLABSize

(7)-XX:OldPLABSize

(8)-XX:ParrallelGCBufferWastePct

(9)G1ReclaimDeadHumongousObjectsAtYoungGC

(10)G1EagerReclaimHumongousObjectsWithStaleRefs

 

(1)-XX:ParallelGCThreads

STW期间,并行GC线程数,默认值为0,通常来说这个值不需要进行设置。

 

(2)-XX:G1RsetScanBlockSize

这个值一般是不需要调整的,除非对于个位数毫秒级别的优化有需求,默认值是64。RSet是一个key-value对组成的数据集合,一个Region共享一个RSet。如果引用关系非常复杂,那么RSet会非常大,所以处理时可分批次处理。每次处理一部分,这样就能计算得更快。

 

不过需要注意的是这个参数和计算机的计算能力是有关的。如果处理器比较强大,计算能力比较强,调大这个参数可以提高效率(相当于减少了取数据的次数)。如果计算能力一般,处理器配置比较差,那么最好不要调整这个参数。因为这个参数如果过大会导致计算速度下降,反而起到反效果。

 

比如,CPU 1ms能处理128个数据的计算,那么调大了这个值为128。虽然会节省提取数据的时间,但如果CPU 1ms只能处理32个数据的计算,那么肯定还是调小时的整体性能更优。

 

(3)-XX:TargetSurvivorRatio

这个值参数指的是Survivor区的使用率,默认值是50。达到50%的Survivor区使用率就可能触发对象进入老年代。

 

即年龄1+年龄2+年龄3 >=50%时,会把年龄3+的对象都升入老年代,这个一般来说也是不需要调整,当然也需要根据具体情况来看。

 

如果程序中有些对象晋升至老年代的速度过快,可考虑增大该值,减缓对象进入老年代的速度。这其实就是动态年龄判断规则。

 

这个值还是会对效率有一点点影响,但基本上也是毫秒级别的影响。一般来说这个值会考虑调大,避免对象进入老年代速度过快,并且可以保证Survivor区的内存也能尽可能的被使用。这个参数对性能整体的影响也体现得并不明显。

 

(4)-XX:ParGCArrayScanChunk

默认值50,指的是如果一个对象数组的大小超过了50,在GC时就不会一次性遍历它,而是每50个元素作为一个chunk去处理。只有最后一次,假如剩余的元素个数是2 * ParGCArrayScanChunk时,才会直接全部处理。

 

这个参数比较冷门,一般不做调整,但这个参数的调整可起到一些效果。增大该值,处理大数组的效率会略有提升,但是会增加栈溢出的风险。减小该值,可以减小栈溢出风险,但是处理效率会略有下降。

 

(5)-XX:+ResizePLAB

默认为true,表示在GC结束后,会调整PLAB的大小。PLAB和TLAB类似,只不过TLAB是指对象分配的缓冲。PLAB指在GC过程中,对象复制时的一块缓冲。PLAB和TLAB有同样的效果,PLAB也是用来提升对象分配的效率的,只不过产生的时机不同。

 

(6)-XX:YoungPLABSize

默认值4096,是新生代PLAB缓存的大小。4096这个数字不是指Byte、K、M这类的单位,而是为了服务于不同JVM而产生的。

 

在32位JVM中,因为内存单元最少也需要4个字节。一个字节8位,4*8 = 32位,4096 * 4= 16KB。也就是在32位JVM中因为一位要4个字节,所以用4096这个基数乘以4。如果是64位,则需要4096 * 8 = 32KB。

 

因为该值是GC过程中的复制缓存大小,所以内存充足时可增大该值以提高复制的效率,但有可能增加内存碎片。减小该值可以减少内存碎片,但复制的效率可能会有所下降。

 

当然也不是绝对,因为在新生代GC中,复制操作是给Survivor区复制。如果PLAB过大,造成内存碎片比较多,会造成Survivor区被快速耗尽。导致复制的效率变低,或者晋升老年代的概率变高。所以这个参数要慎重调大,一般在实际调优中,都需要把这个值调小。

 

(7)-XX:OldPLABSize

默认值1024,指老年代的PLAB缓存大小。32位JVM中为4KB,64位JVM中为8KB。

 

注意这个值并不是Mixed GC产生的复制对应的参数,而是从新生代晋升到老年代时PLAB的大小。

 

所以同样会带来内存碎片的问题。但是一般来说,老年代内存空间比较大,可以容忍更多的内存碎片。所以追求效率的话,可以考虑把这个值调大。

 

(8)-XX:ParrallelGCBufferWastePct

默认值10,表示从Eden区到Survivor区或者对象晋升至老年代时,如果PLAB剩余的空间小于该比例,且没办法放入一个晋升的新对象,就会丢弃这个PLAB块,同时去申请一个新的PLAB。

 

所以如果这个值调的比较大,在复制的时候效率会高很多。但是内存浪费会更加严重,类似于TLAB的RefillWaste。

 

(9)G1ReclaimDeadHumongousObjectsAtYoungGC

这个参数可以控制YGC时是否回收大对象分区,默认是true,表示在YGC时回收大对象。

 

当然,默认情况下只会去回收失去引用的大对象所在的分区。这个参数在后续更名为XX:+G1EagerReclaimHumongousObjects。如果需要设置的话,开启这个参数即可。

 

不过有一些研究发现,在YGC时,如果回收大对象可能会引起性能问题,具体的问题地址如下:

https://bugs.openjdk.java.net/browse/JDK-8141637;

这个问题其实是:在这个应用里面,虽然每次YGC的耗时并不长,但是每次YGC中,会有20%的耗时是来源于大对象回收的操作。因为它们的系统会创建一些大对象出来,在一些特殊场景,会导致扫描的过程比较长。

 

如果系统应用出现了大对象回收过程中的耗时占比非常长的情况,可以考虑关闭这个参数。

 

(10)G1EagerReclaimHumongousObjectsWithStaleRefs

这个参数和上面的参数类似,默认为True。这个参数表示,是否要在YGC时判定那些大对象分区可以回收。如果为true,则表示大对象分区的RSet引用数量小于某阈值时可尝试回收。如果为false,则RSet中的引用数必须是0时,才能回收。

 

这个参数一般是和上面的参数配和起来使用的,如果上面的那个参数设置为false,是不会在YGC时回收大对象的。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/869802.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JavaSecLab靶场】Java综合漏洞平台

免责声明: 请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。在我们平时的网络安全工作中,经常会面对各种各样的挑战。比如,进行定期的漏洞扫描、代码审计,甚至是参与红蓝对抗演练时,发现漏洞后往往需要及时将其修复。 最近,我接触到了一款开…

黑群晖最新安装方式|RR新手

引导盘制作 1、下载最新的黑群晖引导镜像原版链接:wjz304/rr 百度云盘:链接:https://pan.baidu.com/s/12z3v_kVYUDdWNzWBWN_NTQ?pwd=e67k2、将下载好的压缩包解压,得到一个后缀为img的文件。3、使用写盘工具Rufus将镜像文件写到u盘中,点击选择,找到解压好后缀为img的文件…

【Node.js渗透】安装与检测基于Electron的应用程序

免责声明: ⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!三、说明 传送门:【Node.js开发】Electron 框架介绍,我们已经了解了创建简单Electron应用程序的过程。 本文将…

器件选型---晶振

如何选型晶振,有那些选型注意事项器件选型---晶振 晶振的种类和区别 晶振大体可分为无源晶振和有源晶振两类,其区别如下:无源晶振(crystal,谐振器):内部是两侧贴着金属极板的石英晶体,必须要依赖外部电路才能进行稳定的震动;无源晶振一般会采取下面的接法来与MCU内部的…

Windows自定义变量打开文件或文件夹

前言全局说明Windows 系统自带很多变量,方便使用。 参照系统设置,我们可以自定义一些变量,快速打开文件或文件夹。 例如: 在运行或文件夹地址栏输入 %TEMP% 就能打开对应文件夹一、说明 1.1 环境: Windows 11 家庭版 23H2 22631.37371.2 环境变量位置 用户变量:自定义的文…

鼠标双击连击解决方案

前言 手里的这是第二个才用1年多就出现双击现象的G102了,太不耐操。我算是信了那群广告狗的邪,才又选了这个鼠标。 鼠标双击解决方法主要有以下几种:玄学方法:朝鼠标里哈一口气; 使用软件忽视短暂间隔内的点击行为; 拆鼠标,调整微动; 重买,选光微动+光手轮USB有线鼠标…

2024.1.15闲话

我抄,原!可能是不知道什么学习笔记捏 阶 使得 \(a^x\equiv 1\pmod m\) 的最小正整数 \(x\) 被称为 \(a\) 模 \(m\) 的阶,记作 \(\delta_m(a)\)。由欧拉定理可知, \(a\perp m\) 是 \(\delta_m(a)\) 存在的充要条件。证明 充分性:若 \(a\perp m\),根据欧拉定理,\(x=\varph…

2024中国网络安全产业势能榜优能企业「运营商行业」典型案例展示

运营商作为通信和网络服务的提供者,其安全性直接影响到全球范围内的信息流通与互联网基础设施的稳定。随着5G、云计算等新兴技术的普及,运营商面临着更高的安全压力。本期将展示运营商在加强网络防护、提升数据安全等方面的创新实践,以保障全球信息传输的安全性。 PS:典型案…

2024.1.15 鲜花

挖掘机技术哪家强 题解挖掘机技术哪家强 题解Bad Apple!! 流れてく 時の中ででも 気だるさが ほらグルグル廻って 私から 離れる心も 見えないわ そう知らない? 自分から 動くこともなく 時の隙間に 流され続けて 知らないわ 周りのことなど 私は私 それだけ 夢見てる? 何も見…

创建虚拟机VMware

创建虚拟机 ZF3R0-FHED2-M80TY-8QYGC-NPKYF YF390-0HF8P-M81RQ-2DXQE-M2UT6 ZF71R-DMX85-08DQY-8YMNC-PPHV81.创建虚拟机(典型更快)创建虚拟机选择“典型”方式避免自动安装,选择稍后安装系统选择虚拟中的系统设置虚拟机名字与位置(注意:不推荐放到C盘,会有权限问题)设置…

后缀自动机 (SAM) 学习笔记

\(\text{后缀自动机 (SAM) 学习笔记}\) 一、定义 字符串 \(s\) 的 SAM 是一个接受 \(s\) 的所有后缀的最小 DFA (确定性有限自动机或确定性有限状态自动机),也就是说:SAM 是一张有向无环图。它的结点是图中的状态,边是状态之间的转移。 SAM 有源点 \(t_0\),且其它各结点均可…

JS-39 Math 对象

Math是JavaScript的原生对象,提供各种数学功能。 Math.abs() 1、Math.abs方法返回参数值的绝对值 Math.abs(1)//1 Math.abs(-1)//1 2、Math.max(),Math.min() Math.max方法返回参数之中最大的那个值,Math.min返回最小的那个值。如果参数为空,Math.min返回Infinity,Math.max返…