CMS(Concurrent Mark Sweep)應用場景
是一種以獲取最短回收停頓時間為目標的收集器,目前很大一部分的Java應用集中在互聯網網站或者基于瀏覽器的B/S系統的服務端上,這類應用通常都會較為關注服務的回應速度,希望系統停頓時間盡可能短,以給用戶帶來良好的互動體驗,CMS收集器就非常符合這類應用的需求,
CMS的運作程序
![]()
CMS收集器是基于標記-清除演算法實作的,整個程序分為四個步驟,包括:
-
初始標記(initial mark)
這個階段是STW的,但僅僅只是標記一下GCRoots能直接關聯到的物件,所以速度很快 -
并發標記(concurrent mark)
并發標記階段就是從GC Roots的直接關聯物件開始遍歷整個物件圖的程序,這個程序耗時較長但是不需要停頓用戶執行緒,可以與垃圾收集執行緒一起并發運行 -
重新標記(remark)
這個階段是STW的,為了修正并發標記期間,因用戶程式繼續運作而導致標記產生變動的那一部分物件的標記記錄,這個階段的停頓時間通常會比初始標記階段稍長一些,但也遠比并發標記階段的時間短; -
并發清除(concurrent sweep)
清理洗掉掉標記階段判斷的已經死亡的物件,由于不需要移動存活物件,所以這個階段也是可以與用戶執行緒同時并發的
CMS的優點
- 并發收集垃圾
- 低延時
CMS的缺點
-
CMS對處理器資源非常敏感,并發標記階段吞吐量較低,雖然不會導致用戶執行緒停頓,但是會導致應用程式變慢,因為有一部分CPU資源被分配給了垃圾收集執行緒4核CPU會分配25%的資源給垃圾回收執行緒,核數越多,分配給垃圾回收執行緒的資源比例占總核數比例會下降,但是當CPU不足4核的時候,本來應用負載就已經很高了,如果再分一半的資源給垃圾收集執行緒就會導致程式的執行速度大幅度降低
-
Con-current ModeFailure 觸發Full GC(STW)交由Serial Old收集器來收集,由于在垃圾收集階段用戶執行緒還需要持續運行,那就還需要預留足夠記憶體空間提供給用戶執行緒使用,因此CMS收集器不能像其他收集器那樣等待到老年代幾乎完全被填滿了再進行收集,必須預留一部分空間供并發收集時的程式運作使用,在JDK5的默認設定下,CMS收集器當老年代使用了68%的空間后就會被激活,這是一個偏保守的設定,如果在實際應用中老年代增長并不是太快,可以適當調高引數-XX:CMSInitiatingOccu-pancyFraction的值來提高CMS的觸發百分比,降低記憶體回收頻率,獲取更好的性能,但如果這個值給的過高,比如90%,這又會更容易面臨另一種風險:要是CMS運行期間預留的記憶體無法滿足程式分配新物件的需要,就會出現一次“并發失敗”(Concurrent Mode Failure),這時候虛擬機將不得不啟動后備預案:凍結用戶執行緒的執行,臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,但這樣停頓時間就很長了,所以這個引數設定得太高將會很容易導致大量的并發失敗產生,性能反而降低,用戶應在生產環境中根據實際應用情況來權衡設定
-
會產生記憶體空間碎片,分配大物件時空間不足提前觸發FGC,CMS是一款基于“標記-清除”演算法實作的收集器,收集結束時會有大量空間碎片產生,空間碎片過多時,將會給大物件分配帶來很大麻煩,往往會出現老年代還有很多剩余空間,但就是無法找到足夠大的連續空間來分配當前物件,而不得不提前觸發一次Full GC,不過也可以通過設定引數盡量的避免這個情況的發生,CMS收集器提供了一個-XX:+UseCMS-CompactAtFullCollection開關引數(默認是開啟的,此引數從JDK 9開始廢棄),用于在CMS收集器不得不進行Full GC時開啟記憶體碎片的合并整理程序,由于這個記憶體整理必須移動存活物件,(在Shenandoah和ZGC出現前)是無法并發的,這樣空間碎片問題是解決了,但停頓時間又會變長,因此虛擬機設計者們還提供了另外一個引數-XX:CMSFullGCsBeforeCompaction(此引數從JDK 9開始廢棄),這個引數的作用是要求CMS收集器在執行過若干次(數量由引數值決定)不整理空間的Full GC之后,下一次進入Full GC前會先進行碎片整理(默認值為0,表示每次進入Full GC時都進行碎片整理)
CMS特別需要注意的引數
- -XX:CMSInitiatingOccu-pancyFraction:設定觸發老年代回收的閾值,避免發生Concurrent Mode Failure引發FGC
- -XX:+UseCMS-CompactAtFullCollection:在CMS收集器不得不進行Full GC時開啟記憶體碎片的合并整理程序
- -XX:CMSFullGCsBeforeCompaction
關于CMS的總結
雖然開創了并發回收垃圾的先河但由于有Con-current ModeFailure會觸發FGC這個致命性的缺點,因此沒有任何版本的JDK采用CMS作為默認的垃圾回收器,JDK9中CMS已經消失,但CMS并發回收垃圾的思想卻一直在延續
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/166804.html
標籤:其他
上一篇:📣Python開發
下一篇:堆疊的壓入、彈出序列
