JVM 性能調優 及 為什么要減少 Full GC


本文為博主原創,未經允許不得轉載:

  系統上線壓測,需要了解系統的瓶頸以及吞吐量,並根據壓測數據進行對應的優化。

  對壓測進行 JVM 性能優化,有兩條思路:

  第一種情況 : 使用壓測工具 jmeter 進行小量並發業務測試, 通過 top 命令查看cpu是否會急速飆升。若在 小並發量壓測時或單獨調試時,出現 cpu 性能飆升,

    那就需要對對應的業務接口進行代碼分析,分析消耗cpu 的原因。

  第二種情況:使用壓測工具jmeter ,jvisulam 等進行大並發量業務測試,並使用 top 命令實時監控 cpu ,以及內存的使用情況,查看 垃圾回收

    MinorGC 和 Full GC 的頻率和情況。根據 GC 的數據進行對應的JVM參數設置,提高系統的可用性。

如何進行第一種情況調優:

  1. CPU 迅速飆升,在業務服務器上進行監控,

    1.通過 top 命令定位到占用 CPU 和內存 最高的線程

    2. 並將對應的線程轉為16進制,通過jstack 查詢該線程的堆棧信息,從而定位到對應的代碼,並進行代碼分析

    3. 進行代碼性能優化

第二種情況調優:

  第二種情況調優屬於 JVM 參數性能調優,主要通過設置 堆(新生代和老年代)的大小以及GC 垃圾回收器,從而提高服務的性能。

    該調優需要在壓測時,需要對該 java 進程實時的垃圾回收情況進行監控。分析在壓測業務吞吐量相對穩定時,GC的回收情況。  

    1. 使用 jstat 命令對指定的java 進程進行實時監控。並計算出一些關鍵數據。並給自己的系統設置一些初始性的JVM 參數:

      比如 堆內存大小,年輕代大小,Eden和Survivor的比例,老年代的大小,大對象的閾值,大齡對象進入老年代的閾值等。 

    2. 查看年輕代對象的增長速率:

      可以執行命令 jstat -gc pid 1000 10 (每隔1秒執行1次命令,共執行10次),通過觀察EU(eden區的使用)來估算每秒eden大概新增多少對象,

    如果系統負載不高,可以把頻率1秒換成1分鍾,甚至10分鍾來觀察整體情況。注意,一般系統可能有高峰期和日常期,所以需要在不

    同的時間分別估算不同情況下對象增長速率。

    3. Young GC的觸發頻率和每次耗時

      知道年輕代對象增長速率我們就能推根據eden區的大小推算出Young GC大概多久觸發一次,Young GC的平均耗時可以通過 YGCT/YGC公式算出,
    根據結果我們大概就能知道系統大概多久會因為Young GC的執行而卡頓多久。
 
    4. 每次Young GC后有多少對象存活和進入老年代
      這個因為之前已經大概知道Young GC的頻率,假設是每5分鍾一次,那么可以執行命令 jstat -gc pid 300000 10 ,觀察每次結果eden,survivor和老年代
    使用的變化情況,在每次gc后eden區使用一般會大幅減少,survivor和老年代都有可能增長,這些增長的對象就是每次Young GC后存活的對象,同時還可以看
    出每次Young GC后進去老年代大概多少對象,從而可以推算出老年代對象增長速率。

    5. Full GC的觸發頻率和每次耗時

      知道了老年代對象的增長速率就可以推算出Full GC的觸發頻率了,Full GC的每次耗時可以用公式 FGCT/FGC 計算得出。

    6. 優化思路其實簡單來說就是盡量讓每次Young GC后的存活對象小於Survivor區域的50%,都留存在年輕代里。

      盡量別讓對象進入老年代。盡量減少Full GC的頻率,避免頻繁Full GC對JVM性能的影響。

    在調試JVM 的堆大小時,可以根據JVM 堆得內存模型圖進行推算參數值:

    

 

 

  為什么要減少 Full GC:

    通過設置JVM 的參數,減少Full GC 觸發的頻率,因為 Full GC 會導致 STW :top一the一World,簡稱STW,指的是Gc事件發生過程中,

  會產生應用程序的停頓。停頓產生時整個應用程序線程都會被暫停,沒有任何響應,有點像卡死的感覺,這個停頓稱為STW。

    為什么要減少 Full GC ,因為 Young GC 每次掃描的對象少,且對象的生命周期較短,容器GC ,而 Full GC 不僅需要掃描清理老年代的

  垃圾對象,還需要清理 metaspace和新生代的垃圾對象,由於老年代中所保存的對象是生命周期較長的對象,不易清理,比較耗時,這就會

  導致 STW 時間變長,服務不可用或卡頓的現象也就越長。 

  

  常用的 JVM 參數配置:

     

參數 說明 實例
-Xms 初始堆大小,默認物理內存的1/64 -Xms512M
-Xmx 最大堆大小,默認物理內存的1/4 -Xms2G
-Xmn 新生代內存大小,官方推薦為整個堆的3/8 -Xmn512M
-Xss 線程堆棧大小,jdk1.5及之后默認1M,之前默認256k -Xss512k
-XX:NewRatio=n 設置新生代和年老代的比值。如:為3,表示年輕代與年老代比值為1:3,年輕代占整個年輕代年老代和的1/4 -XX:NewRatio=3
-XX:SurvivorRatio=n 年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個。如:8,表示Eden:Survivor=8:1:1,一個Survivor區占整個年輕代的1/8 -XX:SurvivorRatio=8
-XX:PermSize=n 永久代初始值,默認為物理內存的1/64 -XX:PermSize=128M
-XX:MaxPermSize=n 永久代最大值,默認為物理內存的1/4 -XX:MaxPermSize=256M
-verbose:class 在控制台打印類加載信息  
-verbose:gc 在控制台打印垃圾回收日志  
-XX:+PrintGC 打印GC日志,內容簡單  
-XX:+PrintGCDetails 打印GC日志,內容詳細  
-XX:+PrintGCDateStamps 在GC日志中添加時間戳  
-Xloggc:filename 指定gc日志路徑 -Xloggc:/data/jvm/gc.log
-XX:+UseSerialGC 年輕代設置串行收集器Serial  
-XX:+UseParallelGC 年輕代設置並行收集器Parallel Scavenge  
-XX:ParallelGCThreads=n 設置Parallel Scavenge收集時使用的CPU數。並行收集線程數。 -XX:ParallelGCThreads=4
-XX:MaxGCPauseMillis=n 設置Parallel Scavenge回收的最大時間(毫秒) -XX:MaxGCPauseMillis=100
-XX:GCTimeRatio=n 設置Parallel Scavenge垃圾回收時間占程序運行時間的百分比。公式為1/(1+n) -XX:GCTimeRatio=19
-XX:+UseParallelOldGC 設置老年代為並行收集器ParallelOld收集器  
-XX:+UseConcMarkSweepGC 設置老年代並發收集器CMS  
-XX:+CMSIncrementalMode 設置CMS收集器為增量模式,適用於單CPU情況。  

    

 

 

  

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM