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堆得內存模型圖進行推算參數值:
為什么要減少FullGC:
通過設置JVM的參數,減少FullGC觸發的頻率,因為FullGC會導致STW :top一the一World,簡稱STW,指的是Gc事件發生過程中,
會產生應用程序的停頓。停頓產生時整個應用程序線程都會被暫停,沒有任何響應,有點像卡死的感覺,這個停頓稱為STW。
為什么要減少FullGC ,因為Young GC每次掃描的對象少,且對象的生命周期較短,容器GC ,而FullGC不僅需要掃描清理老年代的
垃圾對象,還需要清理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情況。 |
總結
以上是生活随笔為你收集整理的JVM 性能调优 及 为什么要减少 Full GC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 教大家用word换证件照背景与衣服怎么用
- 下一篇: 怎么创建具有真实纹理的CG场景岩石?