記錄一次jvm調優過程

1.查看gc情況:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
結果:服務啓動時長是1天,進行了3240左右次minorGC,一共使用時間80s左右。也就是一次minirGC時間是0.02s,FGC是一次,時間是2.2s,fullGC時間過長,需要優化。
1.爲什麼需要優化:
FGC會不會導致請求失敗?
1.1查看GC方式是什麼:
在這裏插入圖片描述
新生代使用的是PS Young Generation回收器,也就是Parallel Scavenge回收器,特點是使用複製算法的多線程serial回收器,跟perNew區別是更注重程序的吞吐量,吞吐量是要儘量保證系統運行時間,減少垃圾回收時間。在回收時會暫停所有的用戶線程。老年代使用的是PS Old Generation回收器,也就是Parallel Scavenge的年老代版本,使用的是標記整理算法。其他特點見新生代。
幾個名詞的解釋:
吞吐量與收集器關注點說明
(A)、吞吐量(Throughput)
CPU用於運行用戶代碼的時間與CPU總消耗時間的比值;
即吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間);
高吞吐量即減少垃圾收集時間,讓用戶代碼獲得更長的運行時間;
(B)、垃圾收集器期望的目標(關注點)
(1)、停頓時間
停頓時間越短就適合需要與用戶交互的程序;
良好的響應速度能提升用戶體驗;
(2)、吞吐量
高吞吐量則可以高效率地利用CPU時間,儘快完成運算的任務;
主要適合在後臺計算而不需要太多交互的任務;
(3)、覆蓋區(Footprint)
在達到前面兩個目標的情況下,儘量減少堆的內存空間;
可以獲得更好的空間局部性;
通過分析GC回收器可以知道在GC回收時會暫停用戶線程,可能會造成短暫的系統不可用。而且我們系統是更注重用戶體驗的系統,應該更加關注垃圾回收的時間而不是系統吞吐量,
優化思路:1.新生代回收時間較短不需要優化
2.老年代使用cms回收器或G1回收器
-XX:+UseConcMarkSweepGC :啓用cms
-XX:ParallelGCThreads=16 :設置垃圾回收時使用的線程數。默認是8,也可以用命令查詢:
在這裏插入圖片描述
-XX:+CMSScavengeBeforeRemark :強制remark之前開始一次minor gc,減少remark的暫停時間
-XX:+CMSParallelRemarkEnabled :並行remark,減少標記時間
-XX:CMSInitiatingOccupancyFraction :老年代佔據多少時進行cms,查看了下默認配置:
java -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark | grep "CMSInitiatingOccupancyFraction "
在這裏插入圖片描述
竟然是-1,也就是老年代滿了的時候再進行cms,暫時不是很確定,但通過日誌看像是的:
在這裏插入圖片描述
後來通過查https://blog.csdn.net/foolishandstupid/article/details/77430875得知計算得到_initiating_occupancy=(100-40+80*40/100)/100=92%。也就是說,如果不配置CMSInitiatingOccupancyFraction參數,默認情況下,initiating_occupancy的值就是92%。這種情況是很危險的。有可能導致cms失敗:Prommotion failed和Concurrent mode failed。
Prommotion failed:這個問題的產生是由於救助空間不夠,從而向年老代轉移對象,年老代沒有足夠的空間來容納這些對象,導致一次full gc的產生。解決這個問題的辦法有兩種完全相反的傾向:增大救助空間、增大年老代或者去掉救助空間。 增大救助空間就是調整-XX:SurvivorRatio參數,這個參數是Eden區和Survivor區的大小比值,默認是32,也就是說Eden區是 Survivor區的32倍大小,要注意Survivo是有兩個區的,因此Surivivor其實佔整個young genertation的1/34。調小這個參數將增大survivor區,讓對象儘量在survitor區呆長一點,減少進入年老代的對象。去掉救助空 間的想法是讓大部分不能馬上回收的數據儘快進入年老代,加快年老代的回收頻率,減少年老代暴漲的可能性,這個是通過將-XX:SurvivorRatio 設置成比較大的值(比如65536)來做到。在我們的應用中,將young generation設置成256M,這個值相對來說比較大了,而救助空間設置成默認大小(1/34),從壓測情況來看,沒有出現prommotion failed的現象,年輕代比較大,從GC日誌來看,minor gc的時間也在5-20毫秒內,還可以接受,因此暫不調整。

Concurrent mode failed的產生是由於CMS回收年老代的速度太慢,導致年老代在CMS完成前就被沾滿,引起full gc,避免這個現象的產生就是調小-XX:CMSInitiatingOccupancyFraction參數的值,讓CMS更早更頻繁的觸發,降低年老代被沾滿的可能。我們的應用暫時負載比較低,在生產環境上年老代的增長非常緩慢,因此暫時設置此參數爲80。在壓測環境下,這個參數的表現還可以,沒有出現過Concurrent mode failed。
G1回收器:
Eden區和survival區比例是否合理
-XX:+PrintTenuringDistribution讓JVM在每次MinorGC後打印出Survivor空間中的對象的年齡分佈

綜上:jvm參數配置參考:
-server -Xms12288m
-Xmx12288m
-XX:NewRatio=2
-XX:SurvivorRatio=4
-XX:MetaspaceSize=1024m
-XX:MaxMetaspaceSize=1024m
-XX:+UseConcMarkSweepGC
-XX:+CMSScavengeBeforeRemark
-XX:+CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=60
-XX:+UseCompressedClassPointers 壓縮類指針
-XX:+UseCompressedOops 壓縮對象指針
日誌相關:
-XX:+PrintTenuringDistribution讓JVM在每次MinorGC後打印出Survivor空間中的對象的年齡分佈
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintHeapAtGC
-XX:+PrintFlagsFinal
-Xloggc:/datalog/tomcat-gc.log
運行半個月的情況:
在這裏插入圖片描述

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