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

一、背景

线上环境下,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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容