一份很有意思的 GC log

2405011-021bbe727dced4c1.png
GC log

这是 HBase 的 GC log。

遗憾由于没有加 -XX:+PrintHeapAtGC 参数,日志只有这些。

暴露的问题:

YGC 时间久,需要 3 至 5 秒,与出现问题之前的 20ms 有很大差距。

2405011-f53623aee3edbca4.png
YGC 时间久

JVM 配置如下:
堆大小 30G。
年轻代 3G,SurvivorRatio = 2,E 和 S 的大小分别为 1.5G 和 0.75G。


从日志中可以推断出,应该是 survivor 区空间少,导致存活对象超出 Desired survivor size = 0.75G * 50% = 402653184b,晋升阈值调整为 1,对象过早进入老年代导致。

图中第一次 YGC 的时间为 20ms,比较正常。加了 PrintTenuringDistribution 参数,看到对象分布。

从很多文章中写到,PrintTenuringDistribution 打印的是 survivor 区的对象分布。

但日志中看到 812976448 total,约等于 775M,大于 survivor 区的 768M。

所以我将这个统计理解成希望进入 survivor to 区的对象分布?

第一次正常 YGC 时,单是年龄为 1 的对象就超过了 survivor 区的大小。

所以 YGC 之后,survivor 区被年龄为 1 的对象填满,并且由于 survivor 区的占比超过了 50%,晋升阈值被调整为 1。在之后的 YGC 中,非新分配对象直接晋升到老年代。

在之后的 YGC 中,可以看到,每次 GC 之后,年轻代占用的内存均为 786432K = 0.75G,恰好为一个 survivor 区的大小。

2405011-3b001ad9b981f991.png
之后 YGC 后的情况

认为之后新分配的存活对象在 YGC 后,占满了 survivor to 区。

但如果将 PrintTenuringDistribution 分布理解成期望进入 survivor 区的对象分布。

但是第一次异常 YGC 发生时,对象总数只用 773677304b 约等于 738M,不足以填满 survivor 区的 768M。

2405011-de69d00ad5dff1d3.png
对象分布

很是疑惑,求指点。

猜你喜欢

转载自blog.csdn.net/weixin_34337265/article/details/87223552