天天看點

記一次簡單的服務啟動GC優化前言症狀優化總結

記一次簡單的服務啟動GC優化

  • 前言
  • 症狀
  • 優化
    • Full GC
    • Young GC
  • 總結

前言

今天上線一個項目的時候在日志裡發現項目啟動的時候頻繁GC,花了點時間分析了一下并且調整了一下JVM參數。

症狀

項目啟動

java -server -Xmx1024m -XX:MaxDirectMemorySize=512M -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.txt -jar xxxxxxxx.jar
           

gc.txt

記一次簡單的服務啟動GC優化前言症狀優化總結

好家夥,一啟動就來9次 Young GC ,2次 Full GC。

現在先用jinfo看看配置參數

記一次簡單的服務啟動GC優化前言症狀優化總結

注意幾個重要參數:

-XX:InitialHeapSize=62914560		//堆初始值
-XX:MaxHeapSize=1073741824	//堆最大值
-MaxDirectMemorySize=536870912	//虛拟機外最大記憶體
           

優化

Full GC

先來分析這兩次Full GC以及它們前面的Young GC

2.536: [GC (Metadata GC Threshold) [PSYoungGen: 19883K->3584K(128512K)] 27143K->12014K(169472K), 0.0158155 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 
2.552: [Full GC (Metadata GC Threshold) [PSYoungGen: 3584K->0K(128512K)] [ParOldGen: 8430K->8782K(32256K)] 12014K->8782K(160768K), [Metaspace: 20409K->20409K(1069056K)], 0.0844666 secs] [Times: user=0.16 sys=0.00, real=0.09 secs]
4.965: [GC (Metadata GC Threshold) [PSYoungGen: 109848K->8697K(247296K)] 119422K->19608K(279552K), 0.0278398 secs] [Times: user=0.03 sys=0.01, real=0.03 secs]
4.993: [Full GC (Metadata GC Threshold) [PSYoungGen: 8697K->0K(247296K)] [ParOldGen: 10910K->14513K(47104K)] 19608K->14513K(294400K), [Metaspace: 33512K->33512K(1081344K)], 0.1136122 secs] [Times: user=0.20 sys=0.00, real=0.11 secs]
           

可以看到兩次Full GC都是由于Metadata GC Threshold造成的。我這裡用的是JDK8,參數裡沒有明确指定metaspace的初始值和上限,這個時候初始值應該是預設的 21M 。問題不大,那我就把它的初始值和上限調大一點吧,調到64M。

措施:

追加元空間初始值

java -server -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=64m -Xmx1024m -XX:MaxDirectMemorySize=512M  -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.txt -jar xxxxxxxx.jar
           

這個時候再檢視gc.txt

記一次簡單的服務啟動GC優化前言症狀優化總結

可以看到已經沒有Full GC了,不過還是有8次Young GC。

Young GC

其實從我的啟動參數裡面就可以看到,堆的容量我隻指定了最大值(-Xmx1024m),并沒有指定初始值。是以可以在配置參數裡面看到 -XX:InitialHeapSize=62082048,即堆的初始容量隻有60m左右。

而JVM預設的新生代和老年代空間占比為 1 : 3,是以新生代在一開始的時候隻有15m的記憶體空間,是以JVM一開始在15m的時候就發生了Young GC。

是以現在要追加新生代和堆的初始值,新生代、老年代的空間占比我就不調了,使用預設的 1 : 3 即可,而堆的初始值調成1024m,這樣新生代的初始值就是256m了。

措施:

追加堆的初始值

java -server -Xms1024m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=64m -Xmx1024m -XX:MaxDirectMemorySize=512M  -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.txt -jar xxxxxxxx.jar
           

現在再來看看gc.txt

記一次簡單的服務啟動GC優化前言症狀優化總結

可以看到隻有兩次Young GC了,這兩次Young GC是在新生代對象準備超過256m的時候發生的……

好家夥,既然如此,那我也不講武德了,我現在就把堆初始值和最大值都調成100G。

記一次簡單的服務啟動GC優化前言症狀優化總結

好吧,公司窮,隻能買得起4G的伺服器。

記一次簡單的服務啟動GC優化前言症狀優化總結

總結

這隻是一次很簡單的JVM啟動參數優化,平時啟動應用的時候還是得多注意注意堆的初始值和最大值配置,元空間這部分也不能忽略了。