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

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

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

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    CMS gc調整實踐(續)

    Posted on 2009-09-22 20:58 dennis 閱讀(3491) 評論(0)  編輯  收藏 所屬分類: java
        在初步確定CMS參數后,系統運行了幾天,今天嘗試在線上打開了GC日志,按阿寶同學的說法是gc日志的開銷比之jstat還小,打開之后發現確實影響很小。打開GC日志之后又發現幾個隱藏的問題比較有價值,這里記錄下。

       首先是系統在啟動的時候有一次System.gc()調用引起的full gc,日志輸出類似這樣:
    1.201: [Full GC (System) 1.201: [CMS: 0K->797K(1310720K), 0.1090540 secs] 29499K->797K(1546688K), [CMS Perm : 5550K->5547K(65536K)], 0.1091860 secs] [Times: user=0.05 sys=0.06, real=0.11 secs]
       可以確認的是我們系統里的代碼絕對沒有調用System.gc()方法,但是不保證第三方代碼有調用,通過搜索代碼引用,后來定位到了mina的ByteBuffer創建上面。Mina 1.1封裝的ByteBuffer的allocate()方法默認創建的是Direct ByteBuffer,而DirectByteBuffer的構造函數里調用了
    Bits.reserveMemory(cap);

    這個方法強制調用了System.gc():
    static void reserveMemory(long size) {

        
    synchronized (Bits.class) {
            
    if (!memoryLimitSet && VM.isBooted()) {
            maxMemory 
    = VM.maxDirectMemory();
            memoryLimitSet 
    = true;
            }
            
    if (size <= maxMemory - reservedMemory) {
            reservedMemory 
    += size;
            
    return;
            }
        }

        System.gc();
        
    try {
            Thread.sleep(
    100);
        } 
    catch (InterruptedException x) {
            
    // Restore interrupt status
            Thread.currentThread().interrupt();
        }
        
    synchronized (Bits.class) {
            
    if (reservedMemory + size > maxMemory)
            
    throw new OutOfMemoryError("Direct buffer memory");
            reservedMemory 
    += size;
        }

        }
        調用這個方法是為了用戶對Direct ByteBuffer的內存可控。而在我們系統中使用的通訊層初始化Decoder的時候通過Mina 1.1創建了一個Direct ByteBuffer,導致了這一次強制的full gc。這個Buffer因為是長期持有的,因此創建Direct類型也還可以接受。

        但是在這次GC后,又發現每隔一個小時就有一次System.gc()引起的full gc,這就太難以忍受了,日志大概是這樣,注意間隔時間都是3600秒左右:
    10570.672: [Full GC (System) 10570.672: [CMS: 779199K->107679K(1310720K), 1.2957430 secs] 872163K->107679K(1546688K), [CMS Perm : 23993K->15595K(65536K)], 1.2959630 secs] [Times: user=1.27 sys=0.02, real=1.30 secs] 
    14171.971: [Full GC (System) 14171.971: [CMS: 680799K->83681K(1310720K), 1.0171580 secs] 836740K->83681K(1546688K), [CMS Perm : 20215K->15599K(65536K)], 1.0173850 secs] [Times: user=0.97 sys=0.01, real=1.02 secs] 
    17774.020: [Full GC (System) 17774.020: [CMS: 676201K->79331K(1310720K), 0.9652670 secs] 817596K->79331K(1546688K), [CMS Perm : 22808K->15619K(65536K)], 0.9655150 secs] [Times: user=0.93 sys=0.02, real=0.97 secs] 
    21374.989: [Full GC (System) 21374.989: [CMS: 677818K->78590K(1310720K), 0.9297080 secs] 822317K->78590K(1546688K), [CMS Perm : 16435K->15593K(65536K)], 0.9299620 secs] [Times: user=0.89 sys=0.01, real=0.93 secs] 
    24976.948: [Full GC (System) 24976.948: [CMS: 659511K->77608K(1310720K), 0.9255360 secs] 794004K->77608K(1546688K), [CMS Perm : 22359K->15594K(65536K)], 0.9257760 secs] [Times: user=0.88 sys=0.02, real=0.93 secs] 
    28578.892: [Full GC (System) 28578.892: [CMS: 562058K->77572K(1310720K), 0.8365500 secs] 735072K->77572K(1546688K), [CMS Perm : 15840K->15610K(65536K)], 0.8367990 secs] [Times: user=0.82 sys=0.00, real=0.84 secs] 
    32179.731: [Full GC (System) 32179.732: [CMS: 549874K->77224K(1310720K), 0.7864400 secs] 561803K->77224K(1546688K), [CMS Perm : 16016K->15597K(65536K)], 0.7866540 secs] [Times: user=0.75 sys=0.01, real=0.79 secs]

        搜遍了源碼和依賴庫,沒有再發現顯式的gc調用,問題只能出在運行時上,突然想起我們的系統使用RMI暴露JMX給監控程序,監控程序通過RMI連接JMX監控系統和告警等,會不會是RMI的分布式垃圾收集導致的?果然,一查資料,RMI的分布式收集會強制調用System.gc()來進行分布式GC,server端的間隔恰好是一個小時,這個參數可以通過:
    -Dsun.rmi.dgc.server.gcInterval=3600000
    來調整。調長時間是一個解決辦法,但是我們更希望能不出現顯式的GC調用,禁止顯式GC調用通過-XX:+DisableExplicitGC是一個辦法,但是禁止了分布式GC會導致什么問題卻是心理沒底,畢竟我們的JMX調用還是很頻繁的,幸運的是JDK6還提供了另一個選項-XX:+ExplicitGCInvokesConcurrent,允許System.gc()也并發運行,調整DGC時間間隔加上這個選項雙管齊下徹底解決了full gc的隱患。

        打開GC日志后發現的另一個問題是remark的時間過長,已經啟用了并行remark,但是時間還是經常超過200毫秒,這個可能的原因有兩個:我們的年老代太大或者觸發CMS的閥值太高了,CMS進行的時候年老代里的對象已經太多。初步的計劃是調小-XX:SurvivorRatio增大救助空間并且降低-XX:CMSInitiatingOccupancyFraction這個閥值。此外,還找到另一個可選參數-XX:+CMSScavengeBeforeRemark,啟用這個選項后,強制remark之前開始一次minor gc,減少remark的暫停時間,但是在remark之后也將立即開始又一次相對較長時間minor gc,如果你的minor gc很快的話可以考慮下這個選項,暫未實驗。


    主站蜘蛛池模板: 国产成人高清精品免费观看| 亚洲综合一区二区| 特级毛片aaaa级毛片免费| 免费看又爽又黄禁片视频1000| 亚洲精品美女久久久久| 久草视频在线免费| 亚洲av无码片在线观看| 免费精品国产自产拍在线观看图片| 亚洲精品午夜在线观看| 69堂人成无码免费视频果冻传媒| 亚洲激情校园春色| 国外成人免费高清激情视频| 亚洲色偷偷综合亚洲av78| 午夜免费不卡毛片完整版| 国产亚洲视频在线观看| 亚洲午夜爱爱香蕉片| 免费一区二区三区| 亚洲婷婷在线视频| 成年女人永久免费观看片| 黄色免费在线网址| 亚洲精品国产精品乱码在线观看| 一级毛片全部免费播放| 亚洲最大无码中文字幕| 午夜国产羞羞视频免费网站| 成人免费777777被爆出| 99人中文字幕亚洲区| 四虎www成人影院免费观看| 一级视频在线免费观看| 久久亚洲国产伦理| A级毛片内射免费视频| 一区二区三区在线免费| 亚洲AV日韩AV鸥美在线观看| 成年在线网站免费观看无广告| 青青草国产免费国产是公开| 亚洲av永久无码精品网站| 毛片免费视频观看| 国产精品免费大片一区二区| 亚洲精品自拍视频| 亚洲日韩在线中文字幕第一页| 免费国产黄网站在线观看视频| 日韩在线视精品在亚洲|