G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用

背景

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

顺便抱怨一句,下图是jhat和jprofiler加载同一个堆文件,jhat直接告诉了OOM的根本原因,而jprofiler直接没有关键信息,不知道是不是软件bug。
G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用
G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用

G1HeapWastePercent和InitiatingHeapOccupancyPercent

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

Getting Started with the G1 Garbage Collector

G1跟之前的垃圾回收器一样,只是它在老年代回收垃圾时更复杂一点,官方对在老年代的回收整体上称为Concurrent Marking Cycle Phases(并发标记周期阶段),而具体每个阶段做了什么可以详细看官方的说明。
G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用
而 Concurrent Marking Cycle Phases 带来的总结说明文档也有写。大致就是

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

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

G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用

首先第一个是 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 的开始
G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用

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

G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用

结语

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