JVM 性能调优 及 为什么要减少 Full GC
本文為博主原創(chuàng),未經(jīng)允許不得轉(zhuǎn)載:
系統(tǒng)上線壓測,需要了解系統(tǒng)的瓶頸以及吞吐量,并根據(jù)壓測數(shù)據(jù)進行對應(yīng)的優(yōu)化。
對壓測進行 JVM 性能優(yōu)化,有兩條思路:
第一種情況 :使用壓測工具jmeter進行小量并發(fā)業(yè)務(wù)測試,通過 top命令查看cpu是否會急速飆升。若在小并發(fā)量壓測時或單獨調(diào)試時,出現(xiàn) cpu性能飆升,
那就需要對對應(yīng)的業(yè)務(wù)接口進行代碼分析,分析消耗cpu的原因。
第二種情況:使用壓測工具jmeter ,jvisulam等進行大并發(fā)量業(yè)務(wù)測試,并使用 top命令實時監(jiān)控cpu ,以及內(nèi)存的使用情況,查看垃圾回收
MinorGC和Full GC的頻率和情況。根據(jù) GC的數(shù)據(jù)進行對應(yīng)的JVM參數(shù)設(shè)置,提高系統(tǒng)的可用性。
如何進行第一種情況調(diào)優(yōu):
1.CPU迅速飆升,在業(yè)務(wù)服務(wù)器上進行監(jiān)控,
1.通過top命令定位到占用CPU和內(nèi)存 最高的線程
2.并將對應(yīng)的線程轉(zhuǎn)為16進制,通過jstack查詢該線程的堆棧信息,從而定位到對應(yīng)的代碼,并進行代碼分析
3.進行代碼性能優(yōu)化
第二種情況調(diào)優(yōu):
第二種情況調(diào)優(yōu)屬于 JVM參數(shù)性能調(diào)優(yōu),主要通過設(shè)置堆(新生代和老年代)的大小以及GC垃圾回收器,從而提高服務(wù)的性能。
該調(diào)優(yōu)需要在壓測時,需要對該 java進程實時的垃圾回收情況進行監(jiān)控。分析在壓測業(yè)務(wù)吞吐量相對穩(wěn)定時,GC的回收情況。
1.使用 jstat命令對指定的java進程進行實時監(jiān)控。并計算出一些關(guān)鍵數(shù)據(jù)。并給自己的系統(tǒng)設(shè)置一些初始性的JVM參數(shù):
比如 堆內(nèi)存大小,年輕代大小,Eden和Survivor的比例,老年代的大小,大對象的閾值,大齡對象進入老年代的閾值等。
2.查看年輕代對象的增長速率:
可以執(zhí)行命令 jstat -gc pid 1000 10 (每隔1秒執(zhí)行1次命令,共執(zhí)行10次),通過觀察EU(eden區(qū)的使用)來估算每秒eden大概新增多少對象,
如果系統(tǒng)負載不高,可以把頻率1秒換成1分鐘,甚至10分鐘來觀察整體情況。注意,一般系統(tǒng)可能有高峰期和日常期,所以需要在不
同的時間分別估算不同情況下對象增長速率。
3.Young GC的觸發(fā)頻率和每次耗時
知道年輕代對象增長速率我們就能推根據(jù)eden區(qū)的大小推算出Young GC大概多久觸發(fā)一次,Young GC的平均耗時可以通過 YGCT/YGC公式算出,
根據(jù)結(jié)果我們大概就能知道系統(tǒng)大概多久會因為Young GC的執(zhí)行而卡頓多久。
4.每次Young GC后有多少對象存活和進入老年代
這個因為之前已經(jīng)大概知道Young GC的頻率,假設(shè)是每5分鐘一次,那么可以執(zhí)行命令 jstat -gc pid 300000 10 ,觀察每次結(jié)果eden,survivor和老年代
使用的變化情況,在每次gc后eden區(qū)使用一般會大幅減少,survivor和老年代都有可能增長,這些增長的對象就是每次Young GC后存活的對象,同時還可以看
出每次Young GC后進去老年代大概多少對象,從而可以推算出老年代對象增長速率。
5.Full GC的觸發(fā)頻率和每次耗時
知道了老年代對象的增長速率就可以推算出Full GC的觸發(fā)頻率了,F(xiàn)ull GC的每次耗時可以用公式 FGCT/FGC 計算得出。
6.優(yōu)化思路其實簡單來說就是盡量讓每次Young GC后的存活對象小于Survivor區(qū)域的50%,都留存在年輕代里。
盡量別讓對象進入老年代。盡量減少Full GC的頻率,避免頻繁Full GC對JVM性能的影響。
在調(diào)試JVM的堆大小時,可以根據(jù)JVM堆得內(nèi)存模型圖進行推算參數(shù)值:
為什么要減少FullGC:
通過設(shè)置JVM的參數(shù),減少FullGC觸發(fā)的頻率,因為FullGC會導(dǎo)致STW :top一the一World,簡稱STW,指的是Gc事件發(fā)生過程中,
會產(chǎn)生應(yīng)用程序的停頓。停頓產(chǎn)生時整個應(yīng)用程序線程都會被暫停,沒有任何響應(yīng),有點像卡死的感覺,這個停頓稱為STW。
為什么要減少FullGC ,因為Young GC每次掃描的對象少,且對象的生命周期較短,容器GC ,而FullGC不僅需要掃描清理老年代的
垃圾對象,還需要清理metaspace和新生代的垃圾對象,由于老年代中所保存的對象是生命周期較長的對象,不易清理,比較耗時,這就會
導(dǎo)致STW時間變長,服務(wù)不可用或卡頓的現(xiàn)象也就越長。
常用的 JVM參數(shù)配置:
| 參數(shù) | 說明 | 實例 |
|---|---|---|
| -Xms | 初始堆大小,默認物理內(nèi)存的1/64 | -Xms512M |
| -Xmx | 最大堆大小,默認物理內(nèi)存的1/4 | -Xms2G |
| -Xmn | 新生代內(nèi)存大小,官方推薦為整個堆的3/8 | -Xmn512M |
| -Xss | 線程堆棧大小,jdk1.5及之后默認1M,之前默認256k | -Xss512k |
| -XX:NewRatio=n | 設(shè)置新生代和年老代的比值。如:為3,表示年輕代與年老代比值為1:3,年輕代占整個年輕代年老代和的1/4 | -XX:NewRatio=3 |
| -XX:SurvivorRatio=n | 年輕代中Eden區(qū)與兩個Survivor區(qū)的比值。注意Survivor區(qū)有兩個。如:8,表示Eden:Survivor=8:1:1,一個Survivor區(qū)占整個年輕代的1/8 | -XX:SurvivorRatio=8 |
| -XX:PermSize=n | 永久代初始值,默認為物理內(nèi)存的1/64 | -XX:PermSize=128M |
| -XX:MaxPermSize=n | 永久代最大值,默認為物理內(nèi)存的1/4 | -XX:MaxPermSize=256M |
| -verbose:class | 在控制臺打印類加載信息 | |
| -verbose:gc | 在控制臺打印垃圾回收日志 | |
| -XX:+PrintGC | 打印GC日志,內(nèi)容簡單 | |
| -XX:+PrintGCDetails | 打印GC日志,內(nèi)容詳細 | |
| -XX:+PrintGCDateStamps | 在GC日志中添加時間戳 | |
| -Xloggc:filename | 指定gc日志路徑 | -Xloggc:/data/jvm/gc.log |
| -XX:+UseSerialGC | 年輕代設(shè)置串行收集器Serial | |
| -XX:+UseParallelGC | 年輕代設(shè)置并行收集器Parallel Scavenge | |
| -XX:ParallelGCThreads=n | 設(shè)置Parallel Scavenge收集時使用的CPU數(shù)。并行收集線程數(shù)。 | -XX:ParallelGCThreads=4 |
| -XX:MaxGCPauseMillis=n | 設(shè)置Parallel Scavenge回收的最大時間(毫秒) | -XX:MaxGCPauseMillis=100 |
| -XX:GCTimeRatio=n | 設(shè)置Parallel Scavenge垃圾回收時間占程序運行時間的百分比。公式為1/(1+n) | -XX:GCTimeRatio=19 |
| -XX:+UseParallelOldGC | 設(shè)置老年代為并行收集器ParallelOld收集器 | |
| -XX:+UseConcMarkSweepGC | 設(shè)置老年代并發(fā)收集器CMS | |
| -XX:+CMSIncrementalMode | 設(shè)置CMS收集器為增量模式,適用于單CPU情況。 |
總結(jié)
以上是生活随笔為你收集整理的JVM 性能调优 及 为什么要减少 Full GC的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 教大家用word换证件照背景与衣服怎么用
- 下一篇: 手机防水不容忽视手机防水不容忽视怎么办