歡迎您光臨本站 註冊首頁

如何馴服java GC導致暫停?使用16GiB

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0
  內存(條)是便宜,很不幸,垃圾回收機制導致的暫停會嚴重影響系統性能,好像JVM內存最多支持2G,作者花費大量時間精力使用32G來提高系統性能,這篇是其心得.
  GC微調是非常和應用有關,該篇的目標要求是:使用10G更大Heaps和嚴格的響應時間(毫秒級別),(吞吐量和延遲性是一對矛盾,這次GC微調主要是追求低延遲).作者項目特點是:
  1.Heap用於在內存中儲存數據結構
  2.Heap大小超過10G
  3.請求時間要求更快
  4.事務是短的(幾百毫秒) 一個事務可以包括幾個請求
  5.內存中數據修改頻率和面積低,不會一秒內修改整個10G內存,每秒更新10M即可.
  此處省略垃圾回收機制原理介紹.....
  總體來說,banq註:JVM分新生代和舊生代,新創建在新生代,通過新生代垃圾回收,如果不能被回收,將逐步轉入舊生代,舊生代內存可以實現緩存In-memeory數據,顯然新舊兩代的垃圾回收演算法最好不一樣,新生代需要頻繁,而舊生代不需要頻繁,如果我們內存緩存控制得好,舊生代就不會啟動垃圾回收機制,這樣就不會導致系統暫停.
  該文介紹如何來進行新生代大小調節,防止垃圾回收機制頻繁啟動,先使用XX:MaxNewSize= -XX:NewSize= 指定新生代大小,使用-XX: PrintGCDetails -XX: PrintTenuringDistribution -XX: PrintGCTimestamps)輸出GC診斷結果.
  有幾個數據需要計算一下:
  新生代收集期間值,整個分配情況,短生命對象的分配大小,長生命對象的分配情況,中等生命對象分配.
  我個人更喜歡使用psi-Probe安裝在tomcat下,一目了然,如附件圖:

  配置恰當的緩存Cache策略來解決GC問題也相當重要,我們提倡基於內存的領域對象編程,大量數據都在緩存中in-memory,如何保證他們的生命周期和JVM的垃圾回收機制不衝突,也是一種實際問題,文章提出下面幾點:
  1.為緩存增加失效期,讓新生代的GC期間要長於緩存的失效期,也就是緩存中對象數據失效后,正好GC啟動后可以回收這些失效對象.
  2.增加延長新生代的GC期間.
  3.在緩存中使用弱引用.緩存產品自己的事,和我們應用者無關.
  4.增加緩存大小,我個人經驗儘可能將資料庫數據以領域對象方式都載入到內存中.
  JVM分配所有對在新生代,然後將倖存對象(一般是緩存中對象)再分配到舊生代,或再分配到新生代,這些對象的拷貝將耗費時間導致新生代收集暫停,兩種選擇:


  1.在第一次收集時,就將對象複製到舊生代
  2.第二次收集時,將對象複製到舊生代.
  第一種辦法將導致一些短生命周期對象複製到舊生代,第二種辦法需要注意新生代垃圾收集的頻度和長生命周期對象是否小.
  對於一個巨大的heap,新生代垃圾收集暫停主要是在空間掃描和複製倖存對象上,在新生代大小上需要取得一個平衡,舊生代大小足夠放入應用的數據,比如JiveJdon一天下來緩存的大小是200K左右(每天啟動的情況下),只要舊生代大小大於這個值即可,不能太大,也不能太小.
  增加新生代大小要增加整個JVM大小,否則就會降低舊生代的內存大小.
  可以配置CMS短期暫停:–XX:CMSWaitDuration –設置收集暫停的最大間隔時間,越大你的應用將被暫停,類似死機沒有反應.XX: CMSScavengeBeforeRemark 可以避免在收集期間同時掃描.
  原文還提到CMS(Concurrent Mark Sweep)激活會導致暫停等等.
  針對不同應用特點進行演算法配置,在線事務處理將耗費響應時間,而批處理將產生大量垃圾,這些都要用不同JVM來處理.


[火星人 ] 如何馴服java GC導致暫停?使用16GiB已經有429次圍觀

http://coctec.com/docs/java/show-post-59914.html