我是靠谱客的博主 慈祥嚓茶,最近开发中收集的这篇文章主要介绍G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用背景G1HeapWastePercent和InitiatingHeapOccupancyPercent结语2020.12.2 号后续补充,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

背景

最近有个算文本相似度的需求,当然这算法copy过来没做过什么验证就直接上线了,然后应用程序莫名就开始OOM,然后进程直接被kill掉,当然一开始我没想起来是这段算法代码的锅,我把java_pid18776.hprof文件down下来先用jprofiler研究了一番,居然发现没有什么大对象,然后我以为是其它原因,比如kafka消费量大导致的问题,然后去折腾jvm参数。直接导致我因为没有找到根本原因白白浪费时间。但是有失必有得,这次我也了解了G1的一些有用的调优参数,帮助我后期更了解G1

顺便抱怨一句,下图是jhat和jprofiler加载同一个堆文件,jhat直接告诉了OOM的根本原因,而jprofiler直接没有关键信息,不知道是不是软件bug。
在这里插入图片描述
在这里插入图片描述

G1HeapWastePercent和InitiatingHeapOccupancyPercent

当然,这篇文章的重点是两个参数的介绍。这里推荐先看看oracle对G1的官方说明。理解g1的基本原理,对调优参数的使用会有帮助

Getting Started with the G1 Garbage Collector

G1跟之前的垃圾回收器一样,只是它在老年代回收垃圾时更复杂一点,官方对在老年代的回收整体上称为Concurrent Marking Cycle Phases(并发标记周期阶段),而具体每个阶段做了什么可以详细看官方的说明。
在这里插入图片描述
而 Concurrent Marking Cycle Phases 带来的总结说明文档也有写。大致就是

  • 可以同时回收年轻代和老年代。
  • 在标记阶段是并发执行(没有STW),
  • 重新标记阶段比CMS效率更高。

而今天我们介绍的两个参数就是在调Concurrent Marking Cycle Phases。

在这里插入图片描述

首先第一个是 XX:InitiatingHeapOccupancyPercent

  • -XX:InitiatingHeapOccupancyPercent=45 - Percentage of the (entire) heap occupancy to start a concurrent GC cycle. It is used by G1 to trigger a concurrent GC cycle based on the occupancy of the entire heap, not just one of the generations. A value of 0 denotes ‘do constant GC cycles’. The default value is 45 (i.e., 45% full or occupied).

第一个参数的意思就是当整个堆占用超过某个百分比时,就会触发并发GC周期,这个百分比默认是45%,我的理解来说,如果你的项目没有大的cpu负载压力,可以适当降低这个值,带来的好处就是提前开始Concurrent Marking Cycle Phases ,进一步来说,回收 年轻代 and 老年代 也会提前开始,这样有利于防止年轻代晋升老年代失败(老年代容量不足)而触发Full GC

如果你调整 InitiatingHeapOccupancyPercent 的值比较低,你就能在gc log 看到下列的语句频繁出现,也就说明了Concurrent Marking Cycle Phases 的开始
在这里插入图片描述

第二个是 -XX:G1HeapWastePercent ,通过-XX:G1HeapWastePercent指定,默认值5%,也就是在全局并发标记结束后能够统计出所有可被回收的垃圾占Heap的比例值,如果超过5%,那么就会触发之后的多轮Mixed GC,mixed gc会同时回收年轻代+老年代,而这个参数可以指定mixed gc触发的时机。而且mixed gc 可以在 gc log中清楚的记录下来。这个参数与InitiatingHeapOccupancyPercent 结合使用的话可以提前回收老年代,让老年代提前释放空间。

在这里插入图片描述

结语

事情的最后,我通过jhat才知道 是因为文本相似算法对于长的文本会产生大量的char二维数组,会瞬间让系统奔溃。而这次介绍的参数虽然没有在这次事故中帮上忙,但也有意外的收获 – 我觉得这两个参数在系统应用压力不是很大的情况下,可以提前释放老年代的空间,防止 Evacuation Failure的发生。对gc优化有着积极意义。

2020.12.2 号后续补充

在有一次看到一篇小米的技术文章,我感觉我对那两个调优参数理解有误,特此来记录一下,先上文章地址,写的很好的一篇gc调优技术文章。
小米Talos GC性能调优实践

在文章里,对InitiatingHeapOccupancyPercent的使用是根据堆实际占用率来定的,比如你一个程序的堆实际占用一直是2个g,整个堆你设置了5g,然后InitiatingHeapOccupancyPercent 设置为45 ,那么触发 并发标记周期阶段 的时机就是你的堆实际占用涨到2.25个g才会触发。这样每次收集老年代才能真正省出容量。拿我一个在线上的es来举例:

优化前关键参数如下

-Xms5g
-Xmx5g
-XX:G1HeapWastePercent=10
-XX:InitiatingHeapOccupancyPercent=30

我们的老年代长期维持在2g左右,那么现在的参数gc表现如何呢?我把gc日志用gceasy网站做了图形化的分析。

可以看到,老年代的实际空间一直是一条平滑的直线,每次只能回收一丁点,回收的效率实在是差。
在这里插入图片描述

young gc 的持续时间也大部分在4s左右
在这里插入图片描述

从gc各阶段发生的次数统计 也能发现gc次数比较多,mixed回收间隔时间平均只有2分钟。
在这里插入图片描述

问题就出在 XX:InitiatingHeapOccupancyPercent 设置太小,之前我喜欢设置小是因为怕老年代早早见顶,而且机器也富有余力,就没在意回收效率,理论上至少要设置 2g/5g = 40%以上,才不会频繁启动 并发标记周期阶段。

随后我重新设置gc参数,将 XX:InitiatingHeapOccupancyPercent提高到50%

-XX:G1HeapWastePercent=10
-XX:InitiatingHeapOccupancyPercent=50

直接上图看效果,老年代不再是一条平滑的曲线,mixgc发生时也能回收一定的内存。

在这里插入图片描述
4s左右的gc次数也大大减少
在这里插入图片描述
gc 并发标记周期阶段 次数也降到了只有十位数,比之前有较大的改观。
在这里插入图片描述

这次调整后,cpu占用也下降了不少,但是这次调整后还有一些4s的young gc存在,我查了下gc 日志,它是 并发标记阶段花费的时间,没有到垃圾回收,没有啥问题。
在这里插入图片描述

最后

以上就是慈祥嚓茶为你收集整理的G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用背景G1HeapWastePercent和InitiatingHeapOccupancyPercent结语2020.12.2 号后续补充的全部内容,希望文章能够帮你解决G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用背景G1HeapWastePercent和InitiatingHeapOccupancyPercent结语2020.12.2 号后续补充所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部