JVM參數調優是一個很頭痛的問題,可能和應用有關係,別人說能夠的對本身不必定管用。下面是本人一些JVM調優的實踐經驗,但願對讀者能有幫助,環境LinuxAS4,resin2.1.17,JDK6.0,2CPU,4G內存,dell2950服務器。
JVM調優
一:JVM調優之串行垃圾回收
也就是默認配置,完成10萬request用時153秒。JVM參數配置以下:
$JAVA_ARGS.=「-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M
-XX:PermSize=256M-XX:MaxPermSize=256M
-XX:MaxTenuringThreshold=7-XX:GCTimeRatio=19
-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps」;
這種配置通常在resin啓動24小時內彷佛沒有大問題,網站能夠正常訪問,但查看日誌發現,在接近24小時時,FullGC執行愈來愈頻繁,大約每隔3分鐘就有一次FullGC,每次FullGC系統會停頓6秒左右,做爲一個網站來講,用戶等待6秒恐怕太長了,因此這種方式有待改善。MaxTenuringThreshold=7表示一個對象若是在救助空間移動7次尚未被回收就放入年老代,GCTimeRatio=19表示java能夠用5%的時間來作垃圾回收,1/(1+19)=1/20=5%.
二:JVM調優之並行回收
完成10萬request用時117秒,配置以下:
$JAVA_ARGS.=「-Dresin.home=$SERVER_ROOT-server-Xmx2048M
-Xms2048M-Xmn512M-XX:PermSize=256M-XX:MaxPermSize=256M
-Xnoclassgc-Xloggc:log/gc.log-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps-XX:+UseParallelGC-XX:ParallelGCThreads=20
-XX:+UseParallelOldGC-XX:MaxGCPauseMillis=500
-XX:+UseAdaptiveSizePolicy-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19」;
並行回收我嘗試過多種組合配置,彷佛都沒什麼用,resin啓動3小時左右就會停頓,時間超過10秒。也有多是參數設置不夠好的緣由,MaxGCPauseMillis表示GC最大停頓時間,在resin剛啓動尚未執行FullGC時系統是正常的,但一旦執行FullGC,MaxGCPauseMillis根本沒有用,停頓時間可能超過20秒,以後會發生什麼我也再也不關心了,趕忙重啓resin,嘗試其餘回收策略。
三:JVM調優之併發回收
完成10萬request用時60秒,比並行回收差很少快一倍,是默認回收策略性能的2.5倍,配置以下:
$JAVA_ARGS.=「-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:+UseConcMarkSweepGC
-XX:MaxTenuringThreshold=7-XX:GCTimeRatio=19
-Xnoclassgc-Xloggc:log/gc.log-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0」;
這個配置雖然不會出現10秒連不上的狀況,但系統重啓3個小時左右,每隔幾分鐘就會有5秒連不上的狀況,查看gc.log,發如今執行ParNewGC時有個promotionfailed錯誤,從而轉向執行FullGC,形成系統停頓,並且會很頻繁,每隔幾分鐘就有一次,因此還得改善。UseCMSCompactAtFullCollection是表是執行FullGC後對內存進行整理壓縮,省得產生內存碎片,CMSFullGCsBeforeCompaction=N表示執行N次FullGC後執行內存壓縮。
四:JVM調優之增量回收
完成10萬request用時171秒,太慢了,配置以下:
$JAVA_ARGS.=「-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-Xincgc」;
彷佛回收得也不太乾淨,並且也對性能有較大影響,不值得試。
五:JVM調優之併發回收的I-CMS模式
和增量回收差很少,完成10萬request用時170秒。配置以下:
$JAVA_ARGS.=「-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps
-XX:+UseConcMarkSweepGC-XX:+CMSIncrementalMode
-XX:+CMSIncrementalPacing
-XX:CMSIncrementalDutyCycleMin=0
-XX:CMSIncrementalDutyCycle=10-XX:-TraceClassUnloading」;
採用了sun推薦的參數,回收效果很差,照樣有停頓,數小時以內就會頻繁出現停頓,什麼sun推薦的參數,照樣很差使。
六:JVM調優之遞增式低暫停收集器
又叫什麼火車式回收,完成10萬request用時153秒,配置以下:
$JAVA_ARGS.=「-Dresin.home=$SERVER_ROOT-server
-Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M
-XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-XX:+UseTrainGC」;
該配置效果也很差,影響性能,因此沒試。
七:相比之下,仍是併發回收比較好,性能比較高,只要能解決ParNewGC(並行回收年輕代)時的promotionfailed錯誤就一切好辦了,查了不少文章,發現引發promotionfailed錯誤的緣由是CMS來不及回收(CMS默認在年老代佔到90%左右纔會執行),年老代又沒有足夠的空間供GC把一些活的對象從年輕代移到年老代,因此執行FullGC.CMSInitiatingOccupancyFraction=70表示年老代佔到約70%時就開始執行CMS,這樣就不會出現FullGC了。SoftRefLRUPolicyMSPerMB這個參數也是我認爲比較有用的,官方解釋是softlyreachableobjectswillremainaliveforsomeamountoftimeafterthelasttimetheywerereferenced.Thedefaultvalueisonesecondoflifetimeperfreemegabyteintheheap,我以爲不必等1秒,因此設置成0.配置以下
$JAVA_ARGS.=「-Dresin.home=$SERVER_ROOT-server-Xms2048M
-Xmx2048M-Xmn512M-XX:PermSize=256M-XX:MaxPermSize=256M
-XX:SurvivorRatio=8-XX:MaxTenuringThreshold=7
-XX:GCTimeRatio=19-Xnoclassgc-XX:+DisableExplicitGC
-XX:+UseParNewGC-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled-XX:-CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=70
-XX:SoftRefLRUPolicyMSPerMB=0-XX:+PrintClassHistogram
-XX:+PrintGCDetails-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationConcurrentTime
-XX:+PrintGCApplicationStoppedTime
-Xloggc:log/gc.log」;
上面這個配置內存上升的很慢,24小時以內幾乎沒有停頓現象,最長的只停滯了0.8s,ParNewGC每30秒左右才執行一次,每次回收約0.2秒,看來問題應該暫時解決了。 java