1. 程式人生 > >CMS gc實踐總結

CMS gc實踐總結

首先感謝阿寶同學的幫助,我才對這個gc演算法的調整有了一定的認識,而不是停留在過去僅僅瞭解的階段。在讀過sun的文件和跟阿寶討論之後,做個小小的總結。
    CMS,全稱Concurrent Low Pause Collector,是jdk1.4後期版本開始引入的新gc演算法,在jdk5和jdk6中得到了進一步改進,它的主要適合場景是對響應時間的重要性需求大於對吞吐量的要求,能夠承受垃圾回收執行緒和應用執行緒共享處理器資源,並且應用中存在比較多的長生命週期的物件的應用。CMS是用於對tenured generation的回收,也就是年老代的回收,目標是儘量減少應用的暫停時間,減少full gc發生的機率,利用和應用程式執行緒併發的垃圾回收執行緒來標記清除年老代。在我們的應用中,因為有快取的存在,並且對於響應時間也有比較高的要求,因此希望能嘗試使用CMS來替代預設的server型JVM使用的並行收集器,以便獲得更短的垃圾回收的暫停時間,提高程式的響應性。
    CMS並非沒有暫停,而是用兩次短暫停來替代序列標記整理演算法的長暫停,它的收集週期是這樣:
    初始標記(CMS-initial-mark) -> 併發標記(CMS-concurrent-mark) -> 重新標記(CMS-remark) -> 併發清除(CMS-concurrent-sweep) ->併發重設狀態等待下次CMS的觸發(CMS-concurrent-reset)。
    其中的1,3兩個步驟需要暫停所有的應用程式執行緒的。第一次暫停從root物件開始標記存活的物件,這個階段稱為初始標記;第二次暫停是在併發標記之後,暫停所有應用程式執行緒,重新標記併發標記階段遺漏的物件(在併發標記階段結束後物件狀態的更新導致)。第一次暫停會比較短,第二次暫停通常會比較長,並且remark這個階段可以並行標記。

    而併發標記、併發清除、併發重設階段的所謂併發,是指一個或者多個垃圾回收執行緒和應用程式執行緒併發地執行

,垃圾回收執行緒不會暫停應用程式的執行,如果你有多於一個處理器,那麼併發收集執行緒將與應用執行緒在不同的處理器上執行,顯然,這樣的開銷就是會降低應用的吞吐量。Remark階段的並行,是指暫停了所有應用程式後,啟動一定數目的垃圾回收程序進行並行標記,此時的應用執行緒是暫停的。

    CMS的young generation的回收採用的仍然是並行複製收集器,這個跟Paralle gc演算法是一致的。

    下面是引數介紹和遇到的問題總結,

1、啟用CMS:-XX:+UseConcMarkSweepGC。 咳咳,這裡犯過一個低階錯誤,竟然將+號寫成了-號

2。CMS預設啟動的回收執行緒數目是  (ParallelGCThreads + 3)/4) ,如果你需要明確設定,可以通過-XX:
ParallelCMSThreads=20來設定,其中ParallelGCThreads是年輕代的並行收集執行緒數

3、CMS是不會整理堆碎片的,因此為了防止堆碎片引起full gc,通過會開啟CMS階段進行合併碎片選項:-XX:+UseCMSCompactAtFullCollection,開啟這個選項一定程度上會影響效能,阿寶的blog裡說也許可以通過配置適當的CMSFullGCsBeforeCompaction來調整效能,未實踐。

4.為了減少第二次暫停的時間,開啟並行remark: -XX:+CMSParallelRemarkEnabled,如果remark還是過長的話,可以開啟-XX:+CMSScavengeBeforeRemark
選項,強制remark之前開始一次minor gc,減少remark的暫停時間,但是在remark之後也將立即開始又一次minor gc。

5.為了避免Perm區滿引起的full gc,建議開啟CMS回收Perm區選項:

+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled


6.預設CMS是在tenured generation沾滿68%的時候開始進行CMS收集,如果你的年老代增長不是那麼快,並且希望降低CMS次數的話,可以適當調高此值:
-XX:CMSInitiatingOccupancyFraction=80

這裡修改成80%沾滿的時候才開始CMS回收。

7.年輕代的並行收集執行緒數預設是(ncpus <= 8) ? ncpus : 3 + ((ncpus * 5) / 8),如果你希望設定這個執行緒數,可以通過-XX:ParallelGCThreads= N 來調整。

8.進入重點,在初步設定了一些引數後,例如:

-server -Xms1536m -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=64m
-XX:MaxPermSize=64m -XX:-UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection
-XX:CMSInitiatingOccupancyFraction=80-XX:+CMSParallelRemarkEnabled
-XX:SoftRefLRUPolicyMSPerMB=0


需要在生產環境或者壓測環境中測量這些引數下系統的表現,這時候需要開啟GC日誌檢視具體的資訊,因此加上引數:

-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:/home/test/logs/gc.log

在執行相當長一段時間內檢視CMS的表現情況,CMS的日誌輸出類似這樣:

4391.322: [GC [1 CMS-initial-mark: 655374K(1310720K)] 662197K(1546688K), 0.0303050 secs] [Times: user=0.02 sys=0.02, real=0.03 secs]
4391.352: [CMS-concurrent-mark-start]
4391.779: [CMS-concurrent-mark: 0.427/0.427 secs] [Times: user=1.24 sys=0.31, real=0.42 secs]
4391.779: [CMS-concurrent-preclean-start]
4391.821: [CMS-concurrent-preclean: 0.040/0.042 secs] [Times: user=0.13 sys=0.03, real=0.05 secs]
4391.821: [CMS-concurrent-abortable-preclean-start]
4392.511: [CMS-concurrent-abortable-preclean: 0.349/0.690 secs] [Times: user=2.02 sys=0.51, real=0.69 secs]
4392.516: [GC[YG occupancy: 111001 K (235968 K)]4392.516: [Rescan (parallel) , 0.0309960 secs]4392.547: [weak refs processing, 0.0417710 secs] [1 CMS-remark: 655734K(1310720K)] 766736K(1546688K), 0.0932010 secs] [Times: user=0.17 sys=0.00, real=0.09 secs]
4392.609: [CMS-concurrent-sweep-start]
4394.310: [CMS-concurrent-sweep: 1.595/1.701 secs] [Times: user=4.78 sys=1.05, real=1.70 secs]
4394.310: [CMS-concurrent-reset-start]
4394.364: [CMS-concurrent-reset: 0.054/0.054 secs] [Times: user=0.14 sys=0.06, real=0.06 secs]


其中可以看到CMS-initial-mark階段暫停了0.0303050秒,而CMS-remark階段暫停了0.0932010秒,因此兩次暫停的總共時間是0.123506秒,也就是123毫秒左右。兩次短暫停的時間之和在200以下可以稱為正常現象。

但是你很可能遇到兩種fail引起full gc:Prommotion failed和Concurrent mode failed。

Prommotion failed的日誌輸出大概是這樣:

 [ParNew (promotion failed): 320138K->320138K(353920K), 0.2365970 secs]42576.951: [CMS: 1139969K->1120688K(
2166784K), 
9.2214860 secs] 1458785K->1120688K(2520704K), 9.4584090 secs]


這個問題的產生是由於救助空間不夠,從而向年老代轉移物件,年老代沒有足夠的空間來容納這些物件,導致一次full gc的產生。解決這個問題的辦法有兩種完全相反的傾向:增大救助空間、增大年老代或者去掉救助空間。增大救助空間就是調整-XX:SurvivorRatio引數,這個引數是Eden區和Survivor區的大小比值,預設是32,也就是說Eden區是Survivor區的32倍大小,要注意Survivo是有兩個區的,因此Surivivor其實佔整個young genertation的1/34。調小這個引數將增大survivor區,讓物件儘量在survitor區呆長一點,減少進入年老代的物件。去掉救助空間的想法是讓大部分不能馬上回收的資料儘快進入年老代,加快年老代的回收頻率,減少年老代暴漲的可能性,這個是通過將-XX:SurvivorRatio 設定成比較大的值(比如65536)來做到。在我們的應用中,將young generation設定成256M,這個值相對來說比較大了,而救助空間設定成預設大小(1/34),從壓測情況來看,沒有出現prommotion failed的現象,年輕代比較大,從GC日誌來看,minor gc的時間也在5-20毫秒內,還可以接受,因此暫不調整。

Concurrent mode failed的產生是由於CMS回收年老代的速度太慢,導致年老代在CMS完成前就被沾滿,引起full gc,避免這個現象的產生就是調小-XX:CMSInitiatingOccupancyFraction引數的值,讓CMS更早更頻繁的觸發,降低年老代被沾滿的可能。我們的應用暫時負載比較低,在生產環境上年老代的增長非常緩慢,因此暫時設定此引數為80。在壓測環境下,這個引數的表現還可以,沒有出現過Concurrent mode failed。


參考資料:
JDK5.0垃圾收集優化之--Don't Pause》 by 江南白衣
《記一次Java GC調整經歷》1,2 by Arbow
Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning
Tuning Garbage Collection with the 5.0 JavaTM Virtual Machine

相關推薦

CMS gc實踐總結

首先感謝阿寶同學的幫助,我才對這個gc演算法的調整有了一定的認識,而不是停留在過去僅僅瞭解的階段。在讀過sun的文件和跟阿寶討論之後,做個小小的總結。    CMS,全稱Concurrent Low Pause Collector,是jdk1.4後期版本開始引入的新gc演

CMS gc實踐總結(糾正併發執行緒數)

首先感謝阿寶同學的幫助,我才對這個gc演算法的調整有了一定的認識,而不是停留在過去僅僅瞭解的階段。在讀過sun的文件和跟阿寶討論之後,做個小小的總結。    CMS,全稱Concurrent Low Pause Collector,是jdk1.4後期版本開始引入的新gc演算

CMS gc 實踐總結

   CMS,全稱Concurrent low pause collector,是jdk1.4後期版本開始引入的新gc演算法,在jdk5和jdk6中得到了進一步的改進,它的主要適合場景是對響應實踐的重要性需求大於吞吐量的要求,能夠承受垃圾回收執行緒和應用執行緒共享處理器資源

HBase最佳實踐CMS GC調優

HBase發展到當下,對其進行的各種優化從未停止,而GC優化更是其中的重中之重。從0.94版本提出MemStoreLAB策略、Memstore Chuck Pool策略對寫快取Memstore進行優化開始,到0.96版本提出BucketCache以及堆外記憶體方案對讀快取BlockCache進行優化,再到後

HBase最佳實踐CMS GC調優(從gc本身參數調優)

部分 實踐 lock 讀寫 cms ofo mst 更多 操作 同誌們,此部分,重要的不能再重要了1、HBase發展到當下,對其進行的各種優化從未停止,而GC優化更是其中的重中之重。hbase gc調優方向從0.94版本提出MemStoreLAB策略、Memstore Ch

atitit.文件上傳帶進度條的實現原理and組件選型and最佳實踐總結O7

private tps cto 協議 post sch 頁面 system osc atitit.文件上傳帶進度條的實現原理and組件選型and最佳實踐總結O7 1. 實現原理 1 2. 大的文件上傳原理::使用applet 1 3. 新的bp 2 1. 性能提升

最詳細的 Android Toolbar 開發實踐總結(轉)

activity resource listener nba flat xmlns mat https ons 轉自:http://www.codeceo.com/article/android-toolbar-develop.html 過年前發了一篇介紹 Transluc

使用Node.js完成的第一個項目的實踐總結

我們 web框架 -s 關閉 arr ber 代碼格式 oot mongoose http://blog.csdn.net/yanghua_kobe/article/details/17199417 項目簡介 這是一個資產管理項目,主要的目的就是實現對資產的無紙化

Threejs 開發3D地圖實踐總結

操作 moved ons pro 變化 delta otto api flat   前段時間連續上了一個月班,加班加點完成了一個3D攻堅項目。也算是由傳統web轉型到webgl圖形學開發中,坑不少,做了一下總結分享。 1、法向量問題   法線是垂直於我們想要照亮的物體表

redis cluster 實踐總結

監聽 截至目前 實踐 啟動 但是 -- 是什麽 size 發現 最近項目接觸到了redis cluster,現在趁著使用做一下總結,記錄一下遇到過的問題,簡單的概述一下常用到的命令和功能。 本篇文章主要是以運維的角度去講述如何去更好的規劃redis cluster和跳坑

mysql實踐總結

read tails ted 增加 自動 err 搜索 where xxx 首先介紹mysql的安裝和基本使用、進階操作、講解mysql的導入導出和自動備份,然後介紹安全模式修改密碼和mysql的全文本搜索功能,最後記錄了個人使用mysql中遇到的問題集,閑暇時我也會多看幾

快速閱讀實踐總結第一期:2017年9月11日——2017年9月24日

實踐 完成 管理類 計劃 小時 習慣 列表 睡眠 養成 一周計劃閱讀六本書 結果第一周閱讀三本書 第二周沒有閱讀成果 實踐失敗 但仍需堅持 問題所在: 不能養成起床閱讀的習慣 書籍選擇有問題,選擇一本需要精讀、總結、實踐的管理類書籍 不能堅持每天閱讀 已完成閱讀列表:

大數據實踐總結分享

大數據 以上是上一季度自己對於大數據相關技術的學習總結,把之前的一些思維導圖集中在一起,便於復習相關知識點。本著人人為我,我為人人的理念,分享給大家。同時,為了學習更有針對性,群友若對哪一個知識點感興趣的,這是一個總目錄,我可以把分知識點的導圖分享給需要的人,我們共同討論,一起進步。 另也將之

第十周課堂實踐總結

訪問 temp object 學分 return 抽象 ide compute 編程 知識總結 數據結構是指相互之間具有(存在)一定聯系(關系)的數據元素的集合。 使用數據結構的三個原因是:效率、抽象和重用性。 數據結構的主要運算包括: 建立(Create)一個數據

Redis架構第四天:Redis Cluster的理論+實踐總結

Redis集群 RedisCluster 實踐總結 1.怎麽才能夠突破單機瓶頸,讓redis支撐海量數據支撐N個redis master node,每個master node都可以掛載多個slave node多master + 讀寫分離 + 高可用 對比replication+sentinal:r

第十二周課堂實踐總結

leo static 總結 -i exc 生成文件 gen AS 長虹 課堂測試補做 碼雲鏈接 代碼檢查:教材p300 Example10_13 - 在長虹電視後增加一臺海爾電視,價格是你學號的後四位 - 提交運行結果截圖 - 刻下推送代碼到碼雲 源代碼 impo

個人作業——軟件工程實踐總結作業

商戶 後端 大牛 實例 task 包括 熬夜 一次 職業 一、請回望開學時的第一次作業,你對於軟件工程課程的想象 1. 對比開篇博客你對課程目標和期待,“希望通過實踐鍛煉,增強計算機專業的能力和就業競爭力”,對比目前的所學所練所得,在哪些方面達到了你的期待和目標,哪些方面還

PHP命令空間namespace及use的用法實踐總結

方便 ive import names hid bsp pre admin 不同 看PHP中的命名空間和use namespace app\admin\model; use think\Model; use think\Db; 綜上可以看出,命名空間就是相當於一個文件夾的路

課堂實踐總結

進行 解決 個數 文件 查詢 我們 最大的 函數 思考 今天,在老師的帶領下,我們學習了一些新的知識-方法。老師讓我們把一個程序模塊化,單元化。用一些小的模塊拼接一個程序,用方法去實現函數。在之後的動手實踐中,我也在嘗試使用這種方法進行編程,取得了不小的收獲。在

小程序項目實踐總結

傳值 page aspectfit MinIP ren cti 卸載 get 顯示 張小龍在朋友圈裏這樣解釋道:小程序是一種不需要下載安裝即可使用的應用,它實現了應用「觸手可及」的夢想,用戶掃一掃或搜一下即可打開應用。也體現了「用完即走」的理念,用戶不用關心是否安裝太多應用