美文网首页
讨论什么时候应该做gc调优及意义

讨论什么时候应该做gc调优及意义

作者: 天草二十六_简村人 | 来源:发表于2022-11-21 14:32 被阅读0次

一、背景

线上环境下,jvm经常发生full gc;运维监控方面,服务健康检测不健康;用户体验方面,经常出现大量的慢接口调用。
经观察,这三者是伴随发生的。起初,我们从慢接口入手,看到接口中的慢主要是在访问数据存储层的时候,但是去数据库却没有看到任何的慢查询日志(包括mongodb和redis);但是能解释为什么服务不健康,服务假死了,不再能够消费任何请求。
所以,我们就先解决导致接口慢的原因(gc)。

二、业务特点

业务上的接口 ,慢大多数都是查询类的 ,会生成大量jvm对象在堆内存中。
先是在年轻代,由young gc回收,如果年轻代的内存不够,则会直接分配到年老代。
年老代的内存大小有限,要回收他们,就只有full gc了。
当然,在年轻代的对象,要想回收,和对象的年龄也有关。

所以,我们的初步思路是增大年轻代的内存,让对象尽可能在young gc就回收了。

目标

  • 年轻代的对象回收,呈现锯齿形。
  • 最终是为了减少full gc

三、jdk8的默认垃圾回收器ParallelGC

Parallel Scavenge + Parallel Old

  • java -XX:+PrintCommandLineFlags -version

-XX:InitialHeapSize=67108864 -XX:MaxHeapSize=1073741824 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC

实际运行的jvm参数是
java -Xms2800m -Xmx2800m -XX:SurvivorRatio=18 -XX:MaxTenuringThreshold=15 -XX:+HeapDumpOnOutOfMemoryError -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=92 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -jar /opt/xx/xxx.jar

参考地址:
MaxTenuringThreshold 年龄大小,默认15

SurvivorRatio 默认8,Eden占新生代的8/10,From幸存区和To幸存区各占新生代的1/10。(它和-Xmn大小有关)

四、jvm体系结构

image.png

五、目标

1、降低 Minor GC 频率

通常情况下,由于新生代空间较小,Eden 区很快被填满,就会导致频繁 Minor GC,因此我们可以通过增大新生代空间来降低 Minor GC 的频率。

可能你会有这样的疑问,扩容 Eden 区虽然可以减少 Minor GC 的次数,但不会增加单次 Minor GC 的时间吗?

我们知道,单次 Minor GC 时间是由两部分组成:T1(扫描新生代)和 T2(复制存活对象)。

假设一个对象在 Eden 区的存活时间为 500ms,Minor GC 的时间间隔是 300ms,那么正常情况下,Minor GC 的时间为:T1+T2。

当我们增大新生代空间,Minor GC 的时间间隔可能会扩大到 600ms,此时一个存活 500ms 的对象就会在 Eden 区中被回收掉,此时就不存在复制存活对象了,

所以再发生 Minor GC 的时间为:两次扫描新生代,即 2T1。可见,扩容后,Minor GC 时增加了 T1,但省去了 T2 的时间。

通常在虚拟机中,复制对象的成本要远高于扫描成本。如果在堆内存中存在较多的长期存活的对象,此时增加年轻代空间,反而会增加 Minor GC 的时间。

如果堆中的短期对象很多,那么扩容新生代,单次 Minor GC 时间不会显著增加。

因此,单次 Minor GC 时间更多取决于 GC 后存活对象的数量,而非 Eden 区的大小。

-Xmn1500m, 之前的年轻代就500m~700m。

2、降低 Full GC 的频率

通常情况下,由于堆内存空间不足或老年代对象太多,会触发 Full GC,频繁的 Full GC 会带来上下文切换,增加系统的性能开销。

我们可以使用哪些方法来降低 Full GC 的频率呢?

减少创建大对象:在平常的业务场景中,我们习惯一次性从数据库中查询出一个大对象用于 web 端显示。 例如,我之前碰到过一个一次性查询出 60 个字段的业务操作,这种大对象如果超过年轻代最大对象阈值,会被直接创建在老年代;
即使被创建在了年轻代,由于年轻代的内存空间有限,通过 Minor GC 之后也会进入到老年代。 这种大对象很容易产生较多的 Full
GC。我们可以将这种大对象拆解出来,首次只查询一些比较重要的字段,如果还需要其它字段辅助查看,再通过第二次查询显示剩余的字段。

增大堆内存空间:在堆内存不足的情况下,增大堆内存空间,且设置初始化堆内存为最大堆内存,也可以降低 Full GC 的频率。

把jvm堆内存由2800m --> 3800m, 且两者一样大 -Xms3800m -Xmx3800m

3、垃圾回收器为CMS

-XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=92 -XX:+UseCMSInitiatingOccupancyOnly

image.png
  • -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
    新生代使用ParNew,老年代使用CMS

  • -XX:+CMSParallelRemarkEnabled
    降低标记停顿

  • -XX:CMSInitiatingOccupancyFraction=92

参考:

六、调整后的效果对比

1、full gc 频率显著减少

2、慢接口不再剧增

3、年轻代内存增大

  • 调整前


    image.png
  • 调整后
    年轻代的内存呈现锯齿形,说明年轻代的对象得到了及时回收。


    image.png

4、老年代的内存增速显著变慢

七、总结

1、AdaptiveSizePolicy

idea在配置启动参数-XX:SurvivorRatio时不生效的问题,是因为JDK 1.8 默认使用 UseParallelGC 垃圾回收器,该垃圾回收器默认启动了 AdaptiveSizePolicy(自适应大小策略),会根据GC的情况自动计算计算 Eden、From 和 To 区的大小;要使-XX:SurvivorRatio生效,就需要关闭该策略 -XX:-UseAdaptiveSizePolicy。

2、使用CMS时,会默认停用AdaptiveSizePolicy开关

/ # jinfo -flag UseAdaptiveSizePolicy 8

-XX:-UseAdaptiveSizePolicy

验证SurvivorRatio的设置是否生效

jinfo -flag SurvivorRatio 8

-XX:SurvivorRatio=18

验证是否启用了CMS垃圾回收器

jinfo -flag UseConcMarkSweepGC 8

-XX:+UseConcMarkSweepGC

3、在arthas中查看

image.png

相关文章

  • 讨论什么时候应该做gc调优及意义

    一、背景 线上环境下,jvm经常发生full gc;运维监控方面,服务健康检测不健康;用户体验方面,经常出现大量的...

  • JVM-GC调优

    零、本文纲要 一、 GC调优基本思路二、 新生代内存调优三、 老年代内存调优四、 GC调优案例 官方GC调优指南[...

  • 第二十九章、GC调优思路

    以G1 GC 为例,谈谈GC调优思路? 谈到调优,这一定是针对特定场景、特定目的的事情,对于GC调优来说,首先...

  • GC原理及调优

    本文介绍 GC 基础原理和理论,GC 调优方法思路和方法,基于 Hotspot jdk1.8,学习之后你将了解如何...

  • GC原理及调优

    转发于:https://mp.weixin.qq.com/s/sa0j5gQ08luTicTpZW_Cyg“ 本文...

  • JVM性能调优的6大步骤,及关键调优参数详解

    JVM内存调优 对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数。 1.Full GC ...

  • Java架构师面试题——JVM性能调优

    JVM内存调优 对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数。 1.Full GC ...

  • java-GC分析

    主要关注点: GC日志分析 调优命令 调优工具 GC日志分析 摘录GC日志一部分(前段为年轻代gc回收;后段为fu...

  • JVM GC调优入门

    JVM GC调优入门 这篇文章会介绍几个常用的调优参数,再通过两个案例介绍如何进行JVM GC调优。阅读这篇文章的...

  • 使用GCViewer调优GC

    在对 GC 调优的过程中,我们不仅需要知道 GC 的原理,更重要的是要熟练使用各种监控和分析工具,具备 GC 调优...

网友评论

      本文标题:讨论什么时候应该做gc调优及意义

      本文链接:https://www.haomeiwen.com/subject/bovpxdtx.html