GC調優對咱們開發人員來講,若是你想要技術方面一直髮展下去,這部份內容的瞭解是必不可少的,jvm對於工做、面試來講都很重要,GC調優的問題html
更是重中之重,由於是對你jvm學習內容的實踐,知識只有應用實踐出來纔有意義,不然知識紙上談兵。java
首先,咱們須要瞭解的內容,包括:面試
一、jvm內存結構:java虛擬(一)--java內存區域和常量池概念算法
二、垃圾收集算法:java虛擬機(五)--垃圾回收機制GC服務器
三、常見的垃圾收集器:java虛擬機(六)--垃圾收集器和內存分配策略oracle
四、GC日誌分析:java虛擬機(十一)--GC日誌分析 java虛擬機(十二)--可視化工具分析GC日誌jvm
五、jvm常見參數:java虛擬機(九)--經常使用jvm參數ide
PS:本文GC調優非生產環境,只是我的Linux系統對一個簡單項目的啓動調優,經過GC日誌調整相關參數,學習GC調優的方法,最終在生產環境獲得應用工具
網上有不少生產環境GC調優的案例,請自行參考post
一、吞吐量
二、最大停頓時間
一、打印GC日誌
二、根據日誌得到關鍵性能指標
三、分析GC緣由,調優JVM參數
官網建議:
一、除非肯定,不然不要設置最大堆內存
二、優先設置吞吐量目標
三、若是吞吐量目標達不到,調大最大內存,不能讓OS使用Swap,若是任然達不到,下降目標
四、若是吞吐量能達到,GC時間太長,設置停頓時間的目標
首先設置參數:
JAVA_OPTS="-XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs/ -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log"
-XX:+DisableExplicitGC:是指禁止代碼中經過system.gc()主動調用GC
將生成的GC日誌經過GCeasy分析,首先看到吞吐量爲93.78%
發生12GC,2次Full GC,10次Minor GC,Minor GC和Full GC的時間以下:
GC發生的緣由:
其中Ergonomics致使一次Full GC,耗時爲130ms,時間最長
Metadata GC Threshold致使發生1次Full GC,一次Minor GC
Allocation Failure和GCLocker Initiated GC致使9次Minor GC
其中Ergonomics爲jvm的自適應,根據CPU和內存狀況自行調節jvm內存結構,可是也致使了一次Full GC
官方建議:除非很肯定,不然不要設置最大堆內存,因此這裏不調節堆內存
一、由於Metaspace GC Thread出現Full GC,因此這裏選擇調節-XX:MetaspaceSize=64M,由於最大使用了22.74M
吞吐量有了提升,GC次數下降,最大GC Pause爲70ms,因此咱們對於MetaspaceSize的調節是對的
二、對於一個測試項目來講,咱們只是測試啓動GC,95.94%的吞吐量,不夠高,因此這裏測試一下:
-XX:MaxGCPauseMillis=100 -XX:GCTimeRatio=99,最大GC時間位100ms,吞吐量爲99%
發現爲了提升吞吐量,吞吐量有了小幅度提高,可是GC時間卻增加了不少
11次GC中有10次Minor GC,緣由都是Allocation Failure
三、咱們選擇內存動態擴容增量參數,調節爲30,咱們查詢直到,默認爲20%
# jinfo -flag YoungGenerationSizeIncrement 25436 -XX:YoungGenerationSizeIncrement=20
調節發現,吞吐量爲94.346%,因此這裏這個參數不太適合
因此GC調優就是不斷試驗的過程,調優的次數多了,就有了經驗,還有其餘不少參數,均可以試驗測試,查看起到的做用
PS:我這裏測試的參數可能和你的項目以及環境不一樣,起到的做用可能不一樣,例如動態擴容參數,換個項目可能就會有好的做用
官網建議:
一、年輕代大小:
避免使用-Xmn、-XX:NewRatio等顯式設置Young區大小,會覆蓋暫定時間目標
二、暫停時間目標:
暫停時間不要太苛刻,吞吐量目標爲90%,太嚴苛影響吞吐量
三、關於Mixed GC調優參數:
-XX:InitiatingHeapOccupancyPercent:
堆佔有率達到這個數值則觸發global concurrent marking,默認45%
-XX:G1HeapWastePercent:
在global concurrent marking結束以後,能夠知道區中有多少空間要被回收,在每次YGC以後和再次發生Mixed GC以前,會檢查垃圾佔比是
否達到這個參數,若是達到了,下次纔會發生Mixed GC。
-XX:G1MixedGCLiveThresholdPercent:
Old區Region被回收的時候,存貨對象的佔比
-XX:G1MixedGCCountTarget:
-XX:G1OldSetRegionThresholdPercent:
一、默認狀況下
When you see to-space overflow or to-space exhausted messages in your logs, the G1 GC does not have enough memory for either survivor or promoted objects, or for both. The Java heap cannot because it is already at its maximum. Example messages:
924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space exhausted), 0.1957310 secs]
924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space overflow), 0.1957310 secs]
To alleviate the problem, try the following adjustments:
Increase the value of the -XX:G1ReservePercent option (and the total heap accordingly) to increase the amount of reserve memory for "to-space".
Start the marking cycle earlier by reducing the value of -XX:InitiatingHeapOccupancyPercent.
Increase the value of the -XX:ConcGCThreads option to increase the number of parallel marking threads.
上面是官方建議:
對於Mixed GC,能夠增長-XX:G1ReservePercent
選項的值(以及相應的總堆)以增長「to-space」的保留內存量
總共測試四次,以下表格:
最後修改的參數:-XX:GCTimeRatio=100,理論上對於G1垃圾收集器應該是很重要的,由於自己就是強調吞吐量,只是本次測試只是小的測試項目,
並且服務器配置比較渣,只有2個CPU,有些參數沒法試驗
總結:
咱們能夠經過官方文檔的建議,經過GC日誌,結合解析工具,不管是GCeasy仍是GC View都是能夠的,經過發生GC的緣由等問題逐漸調節參數,
官方文檔必定要多看幾遍,我只是簡單瀏覽而已,後面確定會仔細看的。
GC調優指南:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/toc.html
如何選擇垃圾收集器:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html
G1最佳實踐:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc_tuning.html#recommendations
G1 GC的一些關鍵技術:https://zhuanlan.zhihu.com/p/22591838