1. 程式人生 > >JVM調優——之CMS 常見引數解析

JVM調優——之CMS 常見引數解析

 最近在學習使用CMS這個GC,這裡記錄下常用的引數。

1. UseCMSCompactAtFullCollection 與 CMSFullGCsBeforeCompaction

     有一點需要注意的是:CMS併發GC不是“full GC”。HotSpot VM裡對concurrent collection和full collection有明確的區分。所有帶有“FullCollection”字樣的VM引數都是跟真正的full GC相關,而跟CMS併發GC無關的。 
CMSFullGCsBeforeCompaction這個引數在HotSpot VM裡是這樣宣告的:       

product(bool
, UseCMSCompactAtFullCollection, true, \ "Use mark sweep compact at full collections") \ \ product(uintx, CMSFullGCsBeforeCompaction, 0, \ "Number of CMS full collection done before compaction if > 0
") \

然後這樣使用的:

  *should_compact =
    UseCMSCompactAtFullCollection &&
    ((_full_gcs_since_conc_gc >= CMSFullGCsBeforeCompaction) ||
     GCCause::is_user_requested_gc(gch->gc_cause()) ||
     gch->incremental_collection_will_fail(true /* consult_young */));


CMS GC要決定是否在full GC時做壓縮,會依賴幾個條件。其中, 
第一種條件,UseCMSCompactAtFullCollection 與 CMSFullGCsBeforeCompaction 是搭配使用的;前者目前預設就是true了,也就是關鍵在後者上。 
第二種條件是使用者呼叫了System.gc(),而且DisableExplicitGC沒有開啟。 
第三種條件是young gen報告接下來如果做增量收集會失敗;簡單來說也就是young gen預計old gen沒有足夠空間來容納下次young GC晉升的物件。 
上述三種條件的任意一種成立都會讓CMS決定這次做full GC時要做壓縮。 

CMSFullGCsBeforeCompaction 說的是,在上一次CMS併發GC執行過後,到底還要再執行多少次full GC才會做壓縮。預設是0,也就是在預設配置下每次CMS GC頂不住了而要轉入full GC的時候都會做壓縮。 把CMSFullGCsBeforeCompaction配置為10,就會讓上面說的第一個條件變成每隔10次真正的full GC才做一次壓縮(而不是每10次CMS併發GC就做一次壓縮,目前VM裡沒有這樣的引數

)。這會使full GC更少做壓縮,也就更容易使CMS的old gen受碎片化問題的困擾。 本來這個引數就是用來配置降低full GC壓縮的頻率,以期減少某些full GC的暫停時間。CMS回退到full GC時用的演算法是mark-sweep-compact,但compaction是可選的,不做的話碎片化會嚴重些但這次full GC的暫停時間會短些;這是個取捨。

2. -XX:CMSInitiatingOccupancyFraction=70 和-XX:+UseCMSInitiatingOccupancyOnly

    這兩個設定一般配合使用,一般用於『降低CMS GC頻率或者增加頻率、減少GC時長』的需求

   -XX:CMSInitiatingOccupancyFraction=70 是指設定CMS在對記憶體佔用率達到70%的時候開始GC(因為CMS會有浮動垃圾,所以一般都較早啟動GC);

   -XX:+UseCMSInitiatingOccupancyOnly 只是用設定的回收閾值(上面指定的70%),如果不指定,JVM僅在第一次使用設定值,後續則自動調整.

3. -XX:+CMSScavengeBeforeRemark

   在CMS GC前啟動一次ygc,目的在於減少old gen對ygc gen的引用,降低remark時的開銷-----一般CMS的GC耗時 80%都在remark階段

https://www.cnblogs.com/onmyway20xx/p/6605324.html