G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用
背景
最近有個算文本相似度的需求,當(dāng)然這算法copy過來沒做過什么驗證就直接上線了,然后應(yīng)用程序莫名就開始OOM,然后進程直接被kill掉,當(dāng)然一開始我沒想起來是這段算法代碼的鍋,我把java_pid18776.hprof文件down下來先用jprofiler研究了一番,居然發(fā)現(xiàn)沒有什么大對象,然后我以為是其它原因,比如kafka消費量大導(dǎo)致的問題,然后去折騰jvm參數(shù)。直接導(dǎo)致我因為沒有找到根本原因白白浪費時間。但是有失必有得,這次我也了解了G1的一些有用的調(diào)優(yōu)參數(shù),幫助我后期更了解G1
順便抱怨一句,下圖是jhat和jprofiler加載同一個堆文件,jhat直接告訴了OOM的根本原因,而jprofiler直接沒有關(guān)鍵信息,不知道是不是軟件bug。
G1HeapWastePercent和InitiatingHeapOccupancyPercent
當(dāng)然,這篇文章的重點是兩個參數(shù)的介紹。這里推薦先看看oracle對G1的官方說明。理解g1的基本原理,對調(diào)優(yōu)參數(shù)的使用會有幫助
Getting Started with the G1 Garbage Collector
G1跟之前的垃圾回收器一樣,只是它在老年代回收垃圾時更復(fù)雜一點,官方對在老年代的回收整體上稱為Concurrent Marking Cycle Phases(并發(fā)標(biāo)記周期階段),而具體每個階段做了什么可以詳細(xì)看官方的說明。
而 Concurrent Marking Cycle Phases 帶來的總結(jié)說明文檔也有寫。大致就是
- 可以同時回收年輕代和老年代。
- 在標(biāo)記階段是并發(fā)執(zhí)行(沒有STW),
- 重新標(biāo)記階段比CMS效率更高。
而今天我們介紹的兩個參數(shù)就是在調(diào)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).
第一個參數(shù)的意思就是當(dāng)整個堆占用超過某個百分比時,就會觸發(fā)并發(fā)GC周期,這個百分比默認(rèn)是45%,我的理解來說,如果你的項目沒有大的cpu負(fù)載壓力,可以適當(dāng)降低這個值,帶來的好處就是提前開始Concurrent Marking Cycle Phases ,進一步來說,回收 年輕代 and 老年代 也會提前開始,這樣有利于防止年輕代晉升老年代失敗(老年代容量不足)而觸發(fā)Full GC
如果你調(diào)整 InitiatingHeapOccupancyPercent 的值比較低,你就能在gc log 看到下列的語句頻繁出現(xiàn),也就說明了Concurrent Marking Cycle Phases 的開始
第二個是 -XX:G1HeapWastePercent ,通過-XX:G1HeapWastePercent指定,默認(rèn)值5%,也就是在全局并發(fā)標(biāo)記結(jié)束后能夠統(tǒng)計出所有可被回收的垃圾占Heap的比例值,如果超過5%,那么就會觸發(fā)之后的多輪Mixed GC,mixed gc會同時回收年輕代+老年代,而這個參數(shù)可以指定mixed gc觸發(fā)的時機。而且mixed gc 可以在 gc log中清楚的記錄下來。這個參數(shù)與InitiatingHeapOccupancyPercent 結(jié)合使用的話可以提前回收老年代,讓老年代提前釋放空間。
結(jié)語
事情的最后,我通過jhat才知道 是因為文本相似算法對于長的文本會產(chǎn)生大量的char二維數(shù)組,會瞬間讓系統(tǒng)奔潰。而這次介紹的參數(shù)雖然沒有在這次事故中幫上忙,但也有意外的收獲 – 我覺得這兩個參數(shù)在系統(tǒng)應(yīng)用壓力不是很大的情況下,可以提前釋放老年代的空間,防止 Evacuation Failure的發(fā)生。對gc優(yōu)化有著積極意義。
2020.12.2 號后續(xù)補充
在有一次看到一篇小米的技術(shù)文章,我感覺我對那兩個調(diào)優(yōu)參數(shù)理解有誤,特此來記錄一下,先上文章地址,寫的很好的一篇gc調(diào)優(yōu)技術(shù)文章。
小米Talos GC性能調(diào)優(yōu)實踐
在文章里,對InitiatingHeapOccupancyPercent的使用是根據(jù)堆實際占用率來定的,比如你一個程序的堆實際占用一直是2個g,整個堆你設(shè)置了5g,然后InitiatingHeapOccupancyPercent 設(shè)置為45 ,那么觸發(fā) 并發(fā)標(biāo)記周期階段 的時機就是你的堆實際占用漲到2.25個g才會觸發(fā)。這樣每次收集老年代才能真正省出容量。拿我一個在線上的es來舉例:
優(yōu)化前關(guān)鍵參數(shù)如下
-Xms5g -Xmx5g -XX:G1HeapWastePercent=10 -XX:InitiatingHeapOccupancyPercent=30我們的老年代長期維持在2g左右,那么現(xiàn)在的參數(shù)gc表現(xiàn)如何呢?我把gc日志用gceasy網(wǎng)站做了圖形化的分析。
可以看到,老年代的實際空間一直是一條平滑的直線,每次只能回收一丁點,回收的效率實在是差。
young gc 的持續(xù)時間也大部分在4s左右
從gc各階段發(fā)生的次數(shù)統(tǒng)計 也能發(fā)現(xiàn)gc次數(shù)比較多,mixed回收間隔時間平均只有2分鐘。
問題就出在 XX:InitiatingHeapOccupancyPercent 設(shè)置太小,之前我喜歡設(shè)置小是因為怕老年代早早見頂,而且機器也富有余力,就沒在意回收效率,理論上至少要設(shè)置 2g/5g = 40%以上,才不會頻繁啟動 并發(fā)標(biāo)記周期階段。
隨后我重新設(shè)置gc參數(shù),將 XX:InitiatingHeapOccupancyPercent提高到50%
-XX:G1HeapWastePercent=10 -XX:InitiatingHeapOccupancyPercent=50直接上圖看效果,老年代不再是一條平滑的曲線,mixgc發(fā)生時也能回收一定的內(nèi)存。
4s左右的gc次數(shù)也大大減少
gc 并發(fā)標(biāo)記周期階段 次數(shù)也降到了只有十位數(shù),比之前有較大的改觀。
這次調(diào)整后,cpu占用也下降了不少,但是這次調(diào)整后還有一些4s的young gc存在,我查了下gc 日志,它是 并發(fā)標(biāo)記階段花費的時間,沒有到垃圾回收,沒有啥問題。
總結(jié)
以上是生活随笔為你收集整理的G1调优实践日记--G1HeapWastePercent和InitiatingHeapOccupancyPercent的应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拼多多商品推广转链
- 下一篇: 从多张图片重建3D模型(瞎七瞎八写了好多