­

一文徹底搞懂 CMS GC 參數配置

  • 2019 年 11 月 28 日
  • 筆記

近期整理多個 HBase 集群的 JVM 參數,發現都是默認的 CMS GC 配置,如何調優 JVM 參數就成了一個繞不過的話題。因此,為了尋求一個 CMS GC 的 JVM 合理參數配置,筆者參考多篇社區文章及相關部落格,總結了一些 CMS 相關的知識點,以及一套基於 CMS 的 JVM 參數配置。

CMS GC 要點

CMS(Concurrent Mark Sweep,並發-標記-清除)是目前最常用的 JVM 垃圾回收器,這裡不解釋 CMS 的工作過程,只記錄一些基礎要點以幫助理解後面的內容:

  • CMS 是一種基於並發、使用標記清除演算法的垃圾回收器。CMS 會儘可能讓 GC 執行緒與用戶執行緒並發執行,可以消除長時間的 GC 停頓(STW)。
  • CMS 不會對新生代做垃圾回收,默認只針對老年代進行垃圾回收。此外,CMS 還可以開啟對永久代的垃圾回收(或元空間),避免由於 PermGen 空間耗盡帶來 Full GC,JDK6以上受參數 -XX:+CMSClassUnloadingEnabled 控制,這個參數在 JDK8 之前默認關閉,JDK8 默認開啟了。
  • CMS 要與一個新生代垃圾回收器搭配使用,所謂"分代收集"。能與 CMS 配合工作的新生代回收器有 Serial 收集器和 ParNew 收集器,我們一般使用支援多執行緒執行的 ParNew 收集器。
  • 使用 CMS GC 策略時,GC 類別可以分為:Young GC(又稱 Minor GC),Old GC(又稱 Major GC、CMS GC),以及Full GC。其中 Full GC 是對整個堆的垃圾回收,STW 時間較長,對業務影響較大,應該盡量避免 Full GC。

JVM 參數配置

經過理解各個參數的含義及取值影響,總結了以下的 JVM 參數配置,可以幾乎不用調整使用:

-Xmx32g -Xms32g -Xmn1g -Xss256k-XX:SurvivorRatio=2 -XX:MaxPermSize=256m-XX:+UseParNewGC-XX:+UseConcMarkSweepGC-XX:ParallelGCThreads=10-XX:ParallelCMSThreads=16-XX:+CMSParallelRemarkEnabled-XX:MaxTenuringThreshold=15-XX:+UseCMSCompactAtFullCollection-XX:+UseCMSInitiatingOccupancyOnly-XX:CMSInitiatingOccupancyFraction=70-XX:+CMSClassUnloadingEnabled-XX:-DisableExplicitGC-XX:+HeapDumpOnOutOfMemoryError-verbose:gc-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-XX:+PrintGCDateStamps-Xloggc:/app/log/hbase/gc-hbase-REGIONSERVER-`hostname`-`date +%Y%m%d`.log

如果是 64G 及以上的大堆,-Xmn 可以調整到2g,其他參數不變或微調。下面對一些重要的 JVM 參數介紹說明。

重點參數解析

以下參數解析都建立在使用 CMS GC 策略基礎上,這裡使用 CMS GC 表示老年代垃圾回收,Young GC 表示新生代垃圾回收。

-Xmx, -Xms, -Xmn

-Xmx、-Xms 分別表示 JVM 堆的最大值,初始化大小。-Xmx 等價於-XX:MaxHeapSize,-Xms 等價於-XX:InitialHeapSize。

-Xmn表示新生代大小,等價於-XX:MaxNewSize、-XX:NewSize,這個參數的設置對 GC 性能影響較大,設置小了會影響 CMS GC 性能,設置大了會影響 Young GC 性能,建議取值範圍在1~3g,比如32g堆大小時可以設為1g,64g堆大小時可以設為2g,通常性能會比較高。

-Xss

表示執行緒棧的大小,等價於-XX:ThreadStackSize,默認1M,一般使用不了這麼多,建議值256k。

-XX:SurvivorRatio

新生代中 Eden 區與 Survivor 區的比值,默認8,這個參數設置過大會導致 CMS GC 耗時過長,建議調小,使得短壽對象在Young區可以被充分回收,減少晉陞到Old區的對象數量,以此提升 CMS GC 性能。

-XX:+UseParNewGC, -XX:+UseConcMarkSweepGC

分別表示使用並行收集器 ParNew 對新生代進行垃圾回收,使用並發標記清除收集器 CMS 對老年代進行垃圾回收。

-XX:ParallelGCThreads, -XX:ParallelCMSThreads

分別表示 Young GC 與 CMS GC 工作時的並行執行緒數,建議根據處理器數量進行合理設置。

-XX:MaxTenuringThreshold

對象從新生代晉陞到老年代的年齡閾值(每次 Young GC 留下來的對象年齡加一),默認值15,表示對象要經過15次 GC 才能從新生代晉陞到老年代。設置太小會嚴重影響 CMS GC 性能,建議默認值即可。

-XX:+UseCMSCompactAtFullCollection

由於 CMS GC 會產生記憶體碎片,且只在 Full GC 時才會進行記憶體碎片壓縮(因此 使用 CMS 垃圾回收器避免不了 Full GC)。這個參數表示開啟 Full GC 時的壓縮功能,減少記憶體碎片。

-XX:+UseCMSInitiatingOccupancyOnly ,

-XX:CMSInitiatingOccupancyFraction

-XX:CMSInitiatingOccupancyFraction 表示觸發 CMS GC 的老年代使用閾值,一般設置為 70~80(百分比),設置太小會增加 CMS GC 發現的頻率,設置太大可能會導致併發模式失敗或晉陞失敗。默認為 -1,表示 CMS GC 會由 JVM 自動觸發。

-XX:+UseCMSInitiatingOccupancyOnly 表示 CMS GC 只基於 CMSInitiatingOccupancyFraction 觸發,如果未設置該參數則 JVM 只會根據 CMSInitiatingOccupancyFraction 觸發第一次 CMS GC ,後續還是會自動觸發。建議同時設置這兩個參數。

-XX:+CMSClassUnloadingEnabled

表示開啟 CMS 對永久代的垃圾回收(或元空間),避免由於永久代空間耗盡帶來 Full GC。

在線工具

  • GC在線參數檢查與優化:https://xxfox.perfma.com
  • GC在線日誌分析:https://gceasy.io/

參考文檔

  • http://hbasefly.com/2016/08/09/hbase-cms-gc/
  • https://mp.weixin.qq.com/s/gddff77gPdi5s2Hc9HBtcg
  • https://mp.weixin.qq.com/s/euey8visBvINQNOF0AiACQ