一次Java垃圾收集調優實戰(轉載)

7月份的語言排行榜已經出來了,java仍然是主流之一。現在java的應用越來越多,也越來越大,但是,就個人而言對Java的性能還是不甚滿意。寫一下數據挖掘算法時總是顯得力不從心,也許是本身功力不夠吧。。。 對於此,除了加強自己的算法功底外,其實還有一個比較容易的解決辦法:提高jvm的性能。個人認爲這其實是java的web項目調優的一個很好的解決方案。 下面轉了一篇文章,個人覺得不錯,也特別感謝作者的分享:) 原文地址:http://blog.csdn.net/calvinxiu/archive/2008/07/09/2627794.aspx 原文如下:

1 資料

2 GC日誌打印

  GC調優是個很實驗很伽利略的活兒,GC日誌是先決的數據參考和最終驗證:

-XX:+PrintGC Details -XX:+PrintGCTimeStamps(GC發生的時間) -XX:+PrintGCApplicationStoppedTime(GC消耗了多少時間) -XX:+PrintGCApplicationConcurrentTime(GC之間運行了多少時間)

3 收集器選擇

CMS收集器:暫停時間優先

   配置參數:-XX:+UseConcMarkSweepGC    已默認無需配置的參數:-XX:+UseParNewGC(Parallel收集新生代) -XX:+CMSPermGenSweepingEnabled(CMS收集持久代) -XX:UseCMSCompactAtFullCollection(full gc時壓縮年老代)

   初始效果:1g堆內存的新生代約60m,minor gc約5-20毫秒,full gc約130毫秒。

Parallel收集器:吞吐量優先

    配置參數: -XX:+UseParallelGC -XX:+UseParallelOldGC(Parallel收集年老代,從JDK6.0開始支持)

    已默認無需配置的參數: -XX:+UseAdaptiveSizePolicy(動態調整新生代大小)

    初始效果:1g堆內存的新生代約90-110m(動態調整),minor gc約5-20毫秒,full gc有無UseParallelOldGC 參數分別爲1.3/1.1秒,差別不大。

    另外-XX:MaxGCPauseMillis=100 設置minor gc的期望最大時間,JVM會以此來調整新生代的大小,但在此測試環境中對象死的太快,此參數作用不大。

4 調優實戰

      Parallel收集高達1秒的暫停時間基本不可忍受,所以選擇CMS收集器。

      在被壓測的Mule 2.0應用裏,每秒都有大約400M的海量短命對象產生:

  1. 因爲默認60M的新生代太小了,頻繁發生minor gc,大約0.2秒就進行一次。
  2. 因爲CMS收集器中MaxTenuringThreshold(生代對象撐過過多少次minor gc才進入年老代的設置)默認0,存活的臨時對象不經過Survivor區直接進入年老代,不久就佔滿年老代發生full gc。

     對這兩個參數的調優,既要改善上面兩種情況,又要避免新生代過大,複製次數過多造成minor gc的暫停時間過長。

  1. 使用-Xmn調到1/3 總內存。觀察後設置-Xmn500M,新生代實際約460m。(用-XX:NewRatio設置無效,只能用 -Xmn)。
  2. 添加-XX:+PrintTenuringDistribution 參數觀察各個Age的對象總大小,觀察後設置-XX:MaxTenuringThreshold=5。

      優化後,大約1.1秒才發生一次minor gc,且速度依然保持在15-20ms之間。同時年老代的增長速度大大減緩,很久才發生一次full gc,

      參數定稿:

 -Xms1024m -Xmx1024m -Xmn500m -XX:+UseConcMarkSweepGC   -XX:MaxTenuringThreshold=5  -XX:+ExplicitGCInvokesConcurrent

      最後服務處理速度從1180 tps 上升到1380 tps,調整兩個參數提升17%的性能還是筆很划算的買賣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章