本文為博主原創,未經允許不得轉載:
系統上線壓測,需要了解系統的瓶頸以及吞吐量,並根據壓測數據進行對應的優化。
對壓測進行 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的觸發頻率和每次耗時
5. Full GC的觸發頻率和每次耗時
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情況。 |
