<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Rising Sun

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      148 隨筆 :: 0 文章 :: 22 評(píng)論 :: 0 Trackbacks

        首先感謝阿寶同學(xué)的幫助,我才對(duì)這個(gè)gc算法的調(diào)整有了一定的認(rèn)識(shí),而不是停留在過(guò)去僅僅了解的階段。在讀過(guò)sun的文檔和跟阿寶討論之后,做個(gè)小小的總結(jié),如果有謬誤,敬請(qǐng)指正。
        CMS,全稱Concurrent Low Pause Collector,是jdk1.4后期版本開始引入的新gc算法,在jdk5和jdk6中得到了進(jìn)一步改進(jìn),它的主要適合場(chǎng)景是對(duì)響應(yīng)時(shí)間的重要性需求 大于對(duì)吞吐量的要求,能夠承受垃圾回收線程和應(yīng)用線程共享處理器資源,并且應(yīng)用中存在比較多的長(zhǎng)生命周期的對(duì)象的應(yīng)用。CMS是用于對(duì)tenured generation的回收,也就是年老代的回收,目標(biāo)是盡量減少應(yīng)用的暫停時(shí)間,減少full gc發(fā)生的幾率,利用和應(yīng)用程序線程并發(fā)的垃圾回收線程來(lái)標(biāo)記清除年老代。在我們的應(yīng)用中,因?yàn)橛芯彺娴拇嬖冢⑶覍?duì)于響應(yīng)時(shí)間也有比較高的要求,因此希 望能嘗試使用CMS來(lái)替代默認(rèn)的server型JVM使用的并行收集器,以便獲得更短的垃圾回收的暫停時(shí)間,提高程序的響應(yīng)性。
        CMS并非沒(méi)有暫停,而是用兩次短暫停來(lái)替代串行標(biāo)記整理算法的長(zhǎng)暫停,它的收集周期是這樣:
        初始標(biāo)記(CMS-initial-mark) -> 并發(fā)標(biāo)記(CMS-concurrent-mark) -> 重新標(biāo)記(CMS-remark) -> 并發(fā)清除(CMS-concurrent-sweep) ->并發(fā)重設(shè)狀態(tài)等待下次CMS的觸發(fā)(CMS-concurrent-reset)。
        其中的1,3兩個(gè)步驟需要暫停所有的應(yīng)用程序線程的。第一次暫停從root對(duì)象開始標(biāo)記存活的對(duì)象,這個(gè)階段稱為初始標(biāo)記;第二次暫停是在并發(fā)標(biāo)記之后, 暫停所有應(yīng)用程序線程,重新標(biāo)記并發(fā)標(biāo)記階段遺漏的對(duì)象(在并發(fā)標(biāo)記階段結(jié)束后對(duì)象狀態(tài)的更新導(dǎo)致)。第一次暫停會(huì)比較短,第二次暫停通常會(huì)比較長(zhǎng),并且 remark這個(gè)階段可以并行標(biāo)記。

        而并發(fā)標(biāo)記、并發(fā)清除、并發(fā)重設(shè)階段的所謂并發(fā),是指一個(gè)或者多個(gè)垃圾回收線程和應(yīng)用程序線程并發(fā)地運(yùn)行,垃圾回收線程不會(huì)暫停應(yīng)用程序的執(zhí)行,如果你有多于一個(gè)處理器,那么并發(fā)收集線程將與應(yīng)用線程在不同的處理器上運(yùn)行,顯然,這樣的開銷就是會(huì)降低應(yīng)用的吞吐量。Remark階段的并行,是指暫停了所有應(yīng)用程序后,啟動(dòng)一定數(shù)目的垃圾回收進(jìn)程進(jìn)行并行標(biāo)記,此時(shí)的應(yīng)用線程是暫停的。

        CMS的young generation的回收采用的仍然是并行復(fù)制收集器,這個(gè)跟Paralle gc算法是一致的。

        下面是參數(shù)介紹和遇到的問(wèn)題總結(jié),

    1、啟用CMS:-XX:+UseConcMarkSweepGC。 咳咳,這里犯過(guò)一個(gè)低級(jí)錯(cuò)誤,竟然將+號(hào)寫成了-號(hào)

     

    2。CMS默認(rèn)啟動(dòng)的回收線程數(shù)目是  (ParallelGCThreads + 3)/4) ,如果你需要明確設(shè)定,可以通過(guò)-XX:ParallelCMSThreads=20來(lái)設(shè)定,其中ParallelGCThreads是年輕代的并行收集線程數(shù)


    3、CMS是不會(huì)整理堆碎片的,因此為了防止堆碎片引起full gc,通過(guò)會(huì)開啟CMS階段進(jìn)行合并碎片選項(xiàng):-XX:+UseCMSCompactAtFullCollection,開啟這個(gè)選項(xiàng)一定程度上會(huì)影響性能,阿寶的blog里說(shuō)也許可以通過(guò)配置適當(dāng)?shù)腃MSFullGCsBeforeCompaction來(lái)調(diào)整性能,未實(shí)踐。

    4.為了減少第二次暫停的時(shí)間,開啟并行remark: -XX:+CMSParallelRemarkEnabled。如果remark還是過(guò)長(zhǎng)的話,可以開啟-XX:+CMSScavengeBeforeRemark選項(xiàng),強(qiáng)制remark之前開始一次minor gc,減少remark的暫停時(shí)間,但是在remark之后也將立即開始又一次minor gc。

    5.為了避免Perm區(qū)滿引起的full gc,建議開啟CMS回收Perm區(qū)選項(xiàng):

    +CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled


    6.默認(rèn)CMS是在tenured generation沾滿68%的時(shí)候開始進(jìn)行CMS收集,如果你的年老代增長(zhǎng)不是那么快,并且希望降低CMS次數(shù)的話,可以適當(dāng)調(diào)高此值:
    -XX:CMSInitiatingOccupancyFraction=80

    這里修改成80%沾滿的時(shí)候才開始CMS回收。

    7.年輕代的并行收集線程數(shù)默認(rèn)是(cpu <= 8) ? cpu : 3 + ((cpu * 5) / 8),如果你希望降低這個(gè)線程數(shù),可以通過(guò)-XX:ParallelGCThreads= N 來(lái)調(diào)整。

    8.進(jìn)入重點(diǎn),在初步設(shè)置了一些參數(shù)后,例如:

     

    Java代碼  收藏代碼
    1. -server -Xms1536m -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=64m  
    2. -XX:MaxPermSize=64m -XX:-UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection  
    3. -XX:CMSInitiatingOccupancyFraction=80 -XX:+CMSParallelRemarkEnabled  
    4. -XX:SoftRefLRUPolicyMSPerMB=0  

     

    需要在生產(chǎn)環(huán)境或者壓測(cè)環(huán)境中測(cè)量這些參數(shù)下系統(tǒng)的表現(xiàn),這時(shí)候需要打開GC日志查看具體的信息,因此加上參數(shù):

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

    在運(yùn)行相當(dāng)長(zhǎng)一段時(shí)間內(nèi)查看CMS的表現(xiàn)情況,CMS的日志輸出類似這樣:

     

    Java代碼  收藏代碼
    1. 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]  
    2. 4391.352: [CMS-concurrent-mark-start]  
    3. 4391.779: [CMS-concurrent-mark: 0.427/0.427 secs] [Times: user=1.24 sys=0.31, real=0.42 secs]  
    4. 4391.779: [CMS-concurrent-preclean-start]  
    5. 4391.821: [CMS-concurrent-preclean: 0.040/0.042 secs] [Times: user=0.13 sys=0.03, real=0.05 secs]  
    6. 4391.821: [CMS-concurrent-abortable-preclean-start]  
    7. 4392.511: [CMS-concurrent-abortable-preclean: 0.349/0.690 secs] [Times: user=2.02 sys=0.51, real=0.69 secs]  
    8. 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]  
    9. 4392.609: [CMS-concurrent-sweep-start]  
    10. 4394.310: [CMS-concurrent-sweep: 1.595/1.701 secs] [Times: user=4.78 sys=1.05, real=1.70 secs]  
    11. 4394.310: [CMS-concurrent-reset-start]  
    12. 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秒,因此兩次暫停的總共時(shí)間是0.123506秒,也就是123毫秒左右。兩次短暫停的時(shí)間之和在200以下可以稱為正?,F(xiàn)象。

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

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

     

    Java代碼  收藏代碼
    1. [ParNew (promotion failed): 320138K->320138K(353920K), 0.2365970 secs]42576.951: [CMS: 1139969K->1120688K(  
    2. 166784K), 9.2214860 secs] 1458785K->1120688K(2520704K), 9.4584090 secs]  


    這個(gè)問(wèn)題的產(chǎn)生是由于救助空間不夠,從而向年老代轉(zhuǎn)移對(duì)象,年老代沒(méi)有足夠的空間來(lái)容納這些對(duì)象,導(dǎo)致一次full gc的產(chǎn)生。解決這個(gè)問(wèn)題的辦法有兩種完全相反的傾向:增大救助空間、增大年老代或者去掉救助空間。 增大救助空間就是調(diào)整-XX:SurvivorRatio參數(shù),這個(gè)參數(shù)是Eden區(qū)和Survivor區(qū)的大小比值,默認(rèn)是32,也就是說(shuō)Eden區(qū)是 Survivor區(qū)的32倍大小,要注意Survivo是有兩個(gè)區(qū)的,因此Surivivor其實(shí)占整個(gè)young genertation的1/34。調(diào)小這個(gè)參數(shù)將增大survivor區(qū),讓對(duì)象盡量在survitor區(qū)呆長(zhǎng)一點(diǎn),減少進(jìn)入年老代的對(duì)象。去掉救助空 間的想法是讓大部分不能馬上回收的數(shù)據(jù)盡快進(jìn)入年老代,加快年老代的回收頻率,減少年老代暴漲的可能性,這個(gè)是通過(guò)將-XX:SurvivorRatio 設(shè)置成比較大的值(比如65536)來(lái)做到。在我們的應(yīng)用中,將young generation設(shè)置成256M,這個(gè)值相對(duì)來(lái)說(shuō)比較大了,而救助空間設(shè)置成默認(rèn)大小(1/34),從壓測(cè)情況來(lái)看,沒(méi)有出現(xiàn)prommotion failed的現(xiàn)象,年輕代比較大,從GC日志來(lái)看,minor gc的時(shí)間也在5-20毫秒內(nèi),還可以接受,因此暫不調(diào)整。

    Concurrent mode failed的產(chǎn)生是由于CMS回收年老代的速度太慢,導(dǎo)致年老代在CMS完成前就被沾滿,引起full gc,避免這個(gè)現(xiàn)象的產(chǎn)生就是調(diào)小-XX:CMSInitiatingOccupancyFraction參數(shù)的值,讓CMS更早更頻繁的觸發(fā),降低年老代被沾滿的可能。我們的應(yīng)用暫時(shí)負(fù)載比較低,在生產(chǎn)環(huán)境上年老代的增長(zhǎng)非常緩慢,因此暫時(shí)設(shè)置此參數(shù)為80。在壓測(cè)環(huán)境下,這個(gè)參數(shù)的表現(xiàn)還可以,沒(méi)有出現(xiàn)過(guò)Concurrent mode failed。


    參考資料:
    》 by 江南白衣
    《記一次Java GC調(diào)整經(jīng)歷》
    1,2 by Arbow
    Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning
    Tuning Garbage Collection with the 5.0 JavaTM Virtual Machine

    posted on 2012-09-12 12:59 brock 閱讀(1184) 評(píng)論(1)  編輯  收藏

    評(píng)論

    # re: CMS,全稱Concurrent Low Pause Collector gc[未登錄](méi) 2014-08-15 14:12 匿名
    很有用。非常感謝?。。?!  回復(fù)  更多評(píng)論
      


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲国产精品午夜电影| 亚欧国产一级在线免费| 国产成人精品免费视频大全五级| 国产亚洲成在线播放va| 亚洲男同帅GAY片在线观看| 四虎在线免费视频| 猫咪免费人成在线网站| 亚洲av永久无码精品秋霞电影影院| 动漫黄网站免费永久在线观看| 免费福利在线观看| 亚洲成a人片在线观看中文app | 亚洲国产人成中文幕一级二级| 亚洲免费观看视频| 亚洲欧美乱色情图片| 国产亚洲福利精品一区| 嫩草影院在线免费观看| 久久国产精品成人免费| 日韩欧美亚洲中文乱码| 亚洲精品午夜久久久伊人| 亚洲人妻av伦理| 丁香花免费完整高清观看| 免费网站观看WWW在线观看| 亚洲精品色播一区二区| 久久综合日韩亚洲精品色| 全黄性性激高免费视频| 人与禽交免费网站视频| 三级黄色在线免费观看| 亚洲国产日韩a在线播放| 亚洲欧洲综合在线| 好看的电影网站亚洲一区| 亚洲第一视频在线观看免费| 在线永久免费的视频草莓| a级毛片视频免费观看| 国产AV日韩A∨亚洲AV电影| 33333在线亚洲| 亚洲精品不卡视频| 亚洲gv白嫩小受在线观看| 中文字幕在亚洲第一在线| 免费久久精品国产片香蕉| 成年人视频在线观看免费| 最近免费字幕中文大全视频|