您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“G1垃圾回收器在并發場景怎么調優”,內容詳細,步驟清晰,細節處理妥當,希望這篇“G1垃圾回收器在并發場景怎么調優”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
G1管理的最大堆大小為64G。每個Region的大小通過-XX:G1HeapRegionSize
來設置,大小為1~32MB,默認最多可以有2048個Region,G1能管理的最大堆內存是32MB*2048=64G。
使用G1垃圾回收器最小堆內存應為1MB*2048=2GB,低于此值建議使用其它垃圾回收器。
Region大小為1~32MB,具體取值有1MB、2MB、4MB、8MB、16MB、32MB,Region大小優化與大對象有關,當對象占用內存超過Region的一半時將被視為大對象。
被標記為大對象將不利于垃圾回收。
查看本地JVM特別是G1垃圾回收器當前的默認值。
java -XX:+PrintFlagsInitial >> ~/1.txt
G1垃圾回收器有兩種垃圾回收模式,新生代回收和混合回收,特殊情況下會切換到Full GC
。
新生代回收在最大停頓時間內,會處理所有Eden區的垃圾。具體操作是將Eden區所有存活的對象復制到Survivor區,同時清空Eden區。
新生代回收伴隨著應用暫停,最長停頓時間不超過最大停頓時間,新生代回收盡管有暫停機制,考慮到并行回收的特性,回收邏輯相對簡單,回收效率依然較高。一般而言,新生代回收實際耗時通常低于最大停頓時間。
新生代回收觸發時機是新創建的對象在Eden區找不到足夠的存儲空間。
混合回收伴隨著新生代回收和老年代回收,在最大停頓時間范圍內,會處理大部分Eden區的垃圾和一部分老年代垃圾。
老年代回收毫無疑問會伴隨著應用暫停。混合回收操作比較復雜,相對新生代回收來說,單位時間回收的垃圾數要少,回收效率要低。一般而言,混合回收的實際耗時通常接近或者等于最大停頓時間。
混合回收觸發時機是由參數InitiatingHeapOccupancyPercent
控制,默認值為45,含義是老年代占用空間大小與堆的總大小比值超過此數便會觸發混合回收。
默認值45%是比較合理的,不建議所謂的調優。老年代回收策略同樣是將選定Region區內存活的對象復制到空閑Region區,混合回收伴隨著回收新生代垃圾能夠清理出更大的空閑Region區來存放老年區存活對象,保證回收過程能夠正常進行。
老年區存活對象一般較多,對象在內存中復制耗時較長,因此相對來說混合回收效率較低。
Full GC是所有G1垃圾回收調優者盡力回避的情況,單線程回收垃圾,回收對象是整個堆,不再受最長停頓時間約束,一旦出現此情況,意味著應用的響應時間無情的變長。
當應用不定期進入Full GC
狀態時,與其任由其單線程重塑堆內存,不如采用冗余策略,在流量低谷時刻,逐一重啟應用,主動重塑堆內存空間。
流量高峰期出現Full GC現象及其應對策略后面再討論。
參數 | 默認值 | 說明 | 優化建議 |
---|---|---|---|
MaxGCPauseMillis | 200ms | 最大停頓時間 | |
G1HeapRegionSize | 不設置時啟發式推斷 | ||
G1NewSizePercent | 5 | 新生代最小百分比 | |
G1MaxNewSizePercent | 60 | 新生代最大百分比 |
參數 | 默認值 | 說明 | 優化建議 |
---|---|---|---|
ParallelGCThreads | 并行GC線程數,會根據CPU核數推斷 | 默認值 | |
MaxTenuringThreshold | 15 | 從新生代晉升到老年代年齡閾值 | |
SurvivorRatio | 8 | Eden和一個Survivor的比例 | |
TargetSurvivorRatio | 50 | Survivor區內存使用率,增大該值會降低到老年代概率 | |
+G1EagerReclaimHumongousObjects | true | 是否在YGC時回收大對象 |
參數 | 默認值 | 說明 | 優化建議 |
---|---|---|---|
G1MixedGCCountTarget | 8 | 值越大,收集老年代分區越少 | |
G1OldCSetRegionThresholdPercent | 10 | 表示一次最多收集10%的分區 |
垃圾回收器調優的關鍵是盡可能減少Mixed GC的頻率,換句話說盡可能減少垃圾流轉到老年代
。GC調優便是認識垃圾在堆中的流轉規律,從而對流向老年代的垃圾予以提前干涉,使之盡可能留在新生代
。
垃圾在新生代(主要指Eden區)中,垃圾回收使用YGC,回收線程與應用線程并發進行,垃圾回收對應用透明進行,假如CPU算力充足的話,應用幾乎感覺不到垃圾在回收進行。
垃圾在老年代中,垃圾回收采用Mixed GC,回收線程開始工作時,應用線程阻塞,等待回收線程工作完畢有,應用線程重新被喚醒。頻繁的Mixed GC對應用的吞吐量產生不良影響。
一般而言,新創建的對象會存在于新生代的Eden區,下一次垃圾回收處罰便直接回收了。如果對象比較頑強(繼續被其它對象引用),那么會在Survivor區流轉,每GC一次,仍然不能被垃圾回收,那么年齡加一,繼續在S0和S1區流轉,當年齡增長到一定的閾值,直接進入老年代。
新創建的對象如果過大,那么不經過新生代,直接進入老年代。控制對象大小閾值有參數-XX:PretenureSizeThreshold決定,單位字節。
除了對象在S0和S1區反復流轉年齡變化外,垃圾回收維護另外一套獨立的年齡判定規則:如果YGC后尚未被回收的垃圾超過了Survivor區的50%,那么超過的這批對象會直接進入老年代。
12G * 60% * 10% * 50% * 1024 = 737MB
動態年齡判定規則要求每次YGC盡可能的徹底,意味著每次GC的最長時間不能太短,默認200毫秒是比較合理的值。
如果預設置的最長停頓時間過短,那么每次GC后存活大量尚未被回收的垃圾,S區容量有限,不該進入老年代的垃圾快速在老年代堆積,頻繁的Mixed GC不可避免。
在高并發場景下,CPU和內存資源吃緊,負載很高,不確定的性能抖動加速垃圾進入老年代。
舉例說明,DAO層查詢數據庫,一次完整的會話結束后,整個會話中產生的對象垃圾在Eden區應當被全部回收。由于網絡波動,數據庫處理能力的限制,大量會話超時。在此過程中這部分對象垃圾很可能在快速S0和S1流轉中疊加年齡,或者觸發動態年齡判定,直接進入老年代。
老年代內存空間不夠用,觸發Mixed GC,Mixed GC直接副作用是應用卡頓。
Java 8需要手動指定G1垃圾回收器,命令行添加-XX:+UseG1GC參數。
設置內存堆大小有兩點需要注意:初始堆大小與最大堆大小保持一致;堆大小占物理內存大小75%~80%,給系統核心服務預留必要的內存。
參數-Xmx12G
設置初始堆大小;參數-Xms12G
設置最大堆大小。
元空間是指存儲靜態類、靜態方法、常量等特殊變量的內存區域。
參數-XX:MetaspaceSize=1G設置元空間初始大小;參數-XX:MaxMetaspaceSize=1G設置元空間最大大小。
GC停頓時間是指每次YGC
或者Mixed GC
的最大時間,垃圾回收器會根據用戶設置的期望時間動態選擇垃圾掃描的范圍,如果設置時間過小,可能總有一部分垃圾不能得到回收。單位毫秒。
-XX:MaxGCPauseMillis=200
參數-XX:G1NewSizePercent設置新生代初始大小,默認為5%;參數-XX:G1MaxNewSizePercent設置新生代最大大小,默認為60%。
新生代內部細化為 Eden
區和兩個 Survivor
,默認比例是: 8:1:1
Eden: 12G * 60%* 80% = 5.76G S0: 12G * 60%* 10% = 0.72G S1: 12G * 60%* 10% = 0.72G
假設并發系統每秒創建500MB的對象,假設每次YGC根據預先設置的最長停頓時間都能夠掃描到Eden Region,那么此并發系統大約每隔10秒需要進行一次YGC。
GC垃圾回收調優是在物理硬件受限制,并且有調優的理論空間下進行的。條件允許的話,直接升級硬件配置特別是物理內存配置,能夠有效降低GC頻率。比如8C32G或者16C64G等。
當并發量較大時,頻繁的YGC時必然的,單位時間類創建了更多的對象,使用完畢之后成為了垃圾。頻繁的YGC有加速S區對象流向老年代的可能,盡可能保證每次YGC的實際耗時低于預設置的最長垃圾回收時間(默認200毫秒),以便能夠每次都能將新生代垃圾清理完成,盡可能延緩垃圾流向老年代。
在G1垃圾回收器中,沒有所謂的Mixed GC的概念,Mixed GC類似于F·GC,不同的是Mixed GC除了回收老年代,同時也回收新生代,共同之處在于都會產生STW
。
頻繁的Mixed GC
本質是大量應該在新生代回收的垃圾進入了老年代,解決思路是排查哪些哪些垃圾(對象)應該留在新生代,卻流轉到老年代。
檢查應用程序是否周期性的創建大對象,大對象的閾值由參數-XX:PretenureSizeThreshold控制。假如內存有優化空間的前提下適當調高此值,不得超過S區的一半(似乎沒有這么大的對象),副作用是新生代存放對象數量相應變少,Eden區內存更快的用完,YGC相應的變頻繁一些。
從業務的角度來講,大對象產生必有其產生的原因,從這個角度優化可能性不高,垃圾回收器優化盡可能屏蔽業務層代碼,畢竟對開發提要求讓其不要創建大對象不現實。
元空間耗盡也會引發Mixed GC
,考慮到元空間存儲內容的特殊性,因元空間耗盡導致GC頻率提高并沒有很好的辦法。單純提高元空間大小會壓縮新生代大小,新生代變小,對象流轉到老年代的數量會變多,老年代內存消耗加快,同樣會提高GC的頻率。
因元空間耗盡引發的Mixed GC
,相對來說增加物理內存是比較優的解決方式。
盡管Mixed GC
被觸發時,應用會暫時停止響應(默認值是200毫秒),暫停的時間是相對可控的。
如果在進行Mixed GC
時,空閑的Region無法保存存活的對象,Mixed GC無法正常進行時,垃圾回收會切換到 G1 之外的 Serial Old GC
來收集整個堆,包括新生代、老年代、元空間等。
進入Serial Old GC
垃圾回收狀態,垃圾回收不再受最長回收時間約束,采用單線程進行標記、清理和壓縮整理,應用可能進入假死
狀態。也許重啟應用,重新分配堆內存,將堆內存徹底洗牌,也許會更好。
G1垃圾回收調優的關鍵是不要出現Full GC,因此對于敏感的參數千萬不要亂調優,否則不僅達不到理想想過,反而更糟糕。
讀到這里,這篇“G1垃圾回收器在并發場景怎么調優”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。