1. 背景
線上某一個服務(wù)雖然沒有Full GC, 但是Young GC耗時一直居高不下橘荠,更重要的是Olden區(qū)的最大使用量與日遞增个扰。集群機器配置是8C16G了嚎, 使用的是G1垃圾回收器, 目標(biāo)停頓時間是200ms咧七, Xmx和Xms配置是12.8G(機器內(nèi)存的80%)衰齐。
Young GC次數(shù)與耗時如圖1所示,Eden继阻、Survivor耻涛、老年代使用情況如圖2、3瘟檩、4所示抹缕,為展示效果,時間段截取某次發(fā)布后的多天墨辛,可以明顯地看到老年代的最大使用量一直在遞增卓研。
2. 排查與優(yōu)化
剛開始懷疑是有內(nèi)存泄露,但是通過MAT排查沒有發(fā)現(xiàn)問題睹簇,從老年代使用情況來看鉴分,不斷地有對象進入老年代。在排除其他可能后带膀,將懷疑的目光聚集在Region Size。該服務(wù)是一個方案排序服務(wù)橙垢,報文比較大垛叨,幾兆到十幾兆不等。
我們知道G1垃圾收集器與之前垃圾收集器最大的不同就是化整為零柜某,將內(nèi)存區(qū)域分成多個Region嗽元,每個Region可能是E、S喂击、O剂癌、H的一種,如圖5所示翰绊。
其中H代表Humongous佩谷,表示這些Region存儲的是巨大對象(humongous object,H-obj)监嗜,即大小大于等于region一半的對象谐檀。H-obj有如下幾個特征:
- H-obj直接分配到老年代,防止被反復(fù)拷貝移動裁奇。
- H-obj在global concurrent marking階段的cleanup 和 full GC階段回收桐猬。
- 在分配H-obj之前先檢查是否超過 initiating heap occupancy percent和the marking threshold, 如果超過的話,就啟動global concurrent marking刽肠,為的是提早回收溃肪,防止 evacuation failures 和 full GC免胃。
Region size通過heapSize/2048計算得到,也可以通過參數(shù)-XX:G1HeapRegionSize=32m
指定(其中32m指定region size為32M)惫撰,Region size必須是2的指數(shù)羔沙,取值范圍從1M到32M。針對于12.8G的堆內(nèi)存润绎,Region Size是4M撬碟, 前面提到內(nèi)部有很多對象的大小為幾兆到十幾兆,遠大于4M的一半莉撇,因此這些對象會被分配到H區(qū)呢蛤,造成老年代的使用不斷增加。
將Region大小調(diào)到16M或者32M時棍郎,GC情況會有明顯的好轉(zhuǎn)其障,當(dāng)region size 為32M時(16M效果近似),Young GC次數(shù)與耗時如圖6所示涂佃,Eden励翼、Survivor、老年代使用情況如圖7辜荠、8汽抚、9所示。
- Young GC次數(shù):調(diào)整前每分鐘平均10次左右伯病,調(diào)整后為5次左右
- Young GC耗時:調(diào)整前平均耗時400ms造烁,調(diào)整后50ms
- Eden使用情況: 調(diào)整前平均2GB,調(diào)整后3.3GB
- Survivor使用情況:調(diào)整前24MiB午笛,調(diào)整后50MiB
- 老年代使用情況: 調(diào)整前不斷增加惭蟋,調(diào)整后穩(wěn)定在295MiB