JVM性能調(diào)優(yōu)
1 堆設(shè)置調(diào)優(yōu)
年輕代大小選擇
- 響應(yīng)時間優(yōu)先的應(yīng)用:盡可能設(shè)大途戒,直到接近系統(tǒng)的最低響應(yīng)時間限制(根據(jù)實際情況選擇)夺荒。在此種情況下亲善,年輕代收集發(fā)生的頻率也是最小的火俄。同時架谎,減少到達年老代的對象。
- 吞吐量優(yōu)先的應(yīng)用:盡可能的設(shè)置大券膀,可能到達Gbit的程度君纫。因為對響應(yīng)時間沒有要求,垃圾收集可以并行進行芹彬,一般適合8CPU以上的應(yīng)用蓄髓。
通過-XX:NewRadio設(shè)置新生代與老年代的大小比例,通過-Xmn來設(shè)置新生代的大小舒帮。
年老代大小選擇
-
響應(yīng)時間優(yōu)先的應(yīng)用:年老代使用并發(fā)收集器会喝,所以其大小需要小心設(shè)置,一般要考慮并發(fā)會話率和會話持續(xù)時間等一些參數(shù)玩郊。如果堆設(shè)置小了肢执,可以會造成內(nèi)存碎片、高回收頻率以及應(yīng)用暫停而使用傳統(tǒng)的標(biāo)記清除方式译红;如果堆大了预茄,則需要較長的收集時間。最優(yōu)化的方案侦厚,一般需要參考以下數(shù)據(jù)獲得:
- 并發(fā)垃圾收集信息
- 持久代并發(fā)收集次數(shù)
- 傳統(tǒng)GC信息
- 花在年輕代和年老代回收上的時間比例
吞吐量優(yōu)先的應(yīng)用:一般吞吐量優(yōu)先的應(yīng)用都有一個很大的年輕代和一個較小的年老代耻陕。原因是昵慌,這樣可以盡可能回收掉大部分短期對象,減少中期的對象淮蜈,而年老代盡存放長期存活對象。
-
較小堆引起的碎片問題
因為年老代的并發(fā)收集器使用標(biāo)記已卷、清除算法梧田,所以不會對堆進行壓縮。當(dāng)收集器回收時侧蘸,他會把相鄰的空間進行合并裁眯,這樣可以分配給較大的對象。但是讳癌,當(dāng)堆空間較小時穿稳,運行一段時間以后,就會出現(xiàn)“碎片”晌坤,如果并發(fā)收集器找不到足夠的空間逢艘,那么并發(fā)收集器將會停止,然后使用傳統(tǒng)的標(biāo)記骤菠、清除方式進行回收它改。如果出現(xiàn)“碎片”,可能需要進行如下配置:- -XX:+UseCMSCompactAtFullCollection:使用并發(fā)收集器時商乎,開啟對年老代的壓縮央拖。
- -XX:CMSFullGCsBeforeCompaction=0:上面配置開啟的情況下,這里設(shè)置多少次Full GC后鹉戚,對年老代進行壓縮
2 GC策略調(diào)優(yōu)
-
能夠忍受full gc的停頓鲜戒?
是:選擇throughput
否:如果堆較小,使用CMS或者G1抹凳;如果堆較大遏餐,選擇G1
-
使用默認(rèn)配置能達到期望目標(biāo)嗎?
首先盡量使用默認(rèn)配置却桶,因為垃圾收集技術(shù)在不斷發(fā)展成熟境输,自動優(yōu)化大多數(shù)的效果是最好的。如果默認(rèn)配置沒有達到期望颖系,請確認(rèn)垃圾收集是否是性能瓶頸嗅剖。如負(fù)荷較高的應(yīng)用,如果垃圾收集上的時間不超過3%嘁扼,即使進行垃圾回收調(diào)優(yōu)效果也不大信粮。
-
應(yīng)用的停頓時間和預(yù)期的目標(biāo)接近嗎?
是:調(diào)整最大停頓時間設(shè)定可能是需要做的
否:需要進行其他調(diào)整
如果停頓時間太長趁啸,但是吞吐量正常强缘,可以嘗試減少新生代大卸蕉琛(如果是full gc,則減少老年代大新玫唷)赏胚,這樣停頓時間變短,但是單次時間變長
-
GC停頓很短了商虐,但是吞吐量上不去觉阅?
增大堆的大小,但是單次停頓時間會加長
-
使用并發(fā)收集器秘车,發(fā)生了由并發(fā)模式失敗引發(fā)的full gc典勇?
如果CPU資源充足,可以增加并發(fā)GC的線程數(shù)數(shù)
-
使用并發(fā)收集器叮趴,發(fā)生由晉升失敗引起的full gc割笙?
如果是CMS,意味著發(fā)生了碎片化眯亦,這種情況下:使用跟大的堆伤溉;盡早啟動后臺回收
如果堆空間較大,可以選擇使用G1
3 JIT調(diào)優(yōu)
- 一般只需要選擇是使用客戶端版或者服務(wù)器版的JIT編譯器即可妻率。
- 客戶端版的JIT編譯器使用:-client指定谈火,服務(wù)器版的使用:-server。
- 選擇哪種類型一般和硬件的配置相關(guān)舌涨,當(dāng)然隨著硬件的發(fā)展糯耍,也沒有一個確定的標(biāo)準(zhǔn)哪種硬件適合哪種配置。
- 兩種JIT編譯器的區(qū)別:
- Client版對于代碼的編譯早于Server版囊嘉,也意味著代碼的執(zhí)行速度在程序執(zhí)行早期Client版更快温技。
- Server版對代碼的編譯會稍晚一些,這是為了獲取到程序本身的更多信息扭粱,以便編譯得到優(yōu)化程度更高的代碼舵鳞。因為運行在Server上的程序通常都會持續(xù)很久。
- Tiered編譯的原理:
- JVM啟動之初使用Client版JIT編譯器
- 當(dāng)HotSpot形成之后使用Server版JIT編譯器再次編譯
- 在Java 8中琢蛤,默認(rèn)使用Tiered編譯方式蜓堕。
不過在Java7版本之后,一旦開發(fā)人員在程序中顯式指定命令“-server”時博其,缺省將會開啟分層編譯(Tiered Compilation)策略套才,由client編譯器和server編譯器相互協(xié)作共同來執(zhí)行編譯任務(wù)。不過在早期版本中慕淡,開發(fā)人員則只能夠通過命令“-XX:+TieredCompilation”手動開啟分層編譯策略背伴。
- -Xint:完全采用解釋器模式執(zhí)行程序;
- -Xcomp:完全采用即時編譯器模式執(zhí)行程序;
- -Xmixed:采用解釋器+即時編譯器的混合模式共同執(zhí)行程序傻寂。
啟動優(yōu)化
Application | -client | -server | -XX:+TieredCompilation | 類數(shù)量 |
---|---|---|---|---|
HelloWorld | 0.08s | 0.08s | 0.08s | Few |
NetBeans | 2.83s | 3.92s | 3.07s | ~10000 |
HelloWorld | 51.5s | 54.0s | 52.0s | ~20000 |
總結(jié)
- 當(dāng)程序的啟動速度越快越好時息尺,使用Client版的JIT編譯器更好。
- 就啟動速度而言疾掰,Tiered編譯方式的性能和只使用Client的方式十分接近搂誉,因為Tiered編譯本質(zhì)上也會在啟動是使用Client JIT編譯器。
批處理優(yōu)化
對于批處理任務(wù)静檬,任務(wù)量的大小是決定運行時間和使用哪種編譯策略的最重要因素:
Number of Tasks | -client | -server | -XX:+TieredCompilation |
---|---|---|---|
1 | 0.142s | 0.176s | 0.165s |
10 | 0.211s | 0.348s | 0.226s |
100 | 0.454s | 0.674s | 0.472s |
1000 | 2.556s | 2.158s | 1.910s |
10000 | 23.78s | 14.03s | 13.56s |
可以發(fā)現(xiàn)幾個結(jié)論:
- 當(dāng)任務(wù)數(shù)量小的時候勒葱,使用Client或者Tiered方式的性能類似,而當(dāng)任務(wù)數(shù)量大的時候巴柿,使用Tiered會獲得最好的性能,因為它綜合使用了Client和Server兩種編譯器死遭,在程序運行之初广恢,使用Client JIT編譯器得到一部分編譯過的代碼,在程序“熱點”逐漸形成之后呀潭,使用Server JIT編譯器得到高度優(yōu)化的編譯后代碼钉迷。
- Tiered編譯方式的性能總是好于單獨使用Server JIT編譯器。
- Tiered編譯方式在任務(wù)量不大的時候钠署,和單獨使用Client JIT編譯器的性能相當(dāng)糠聪。
總結(jié)
- 當(dāng)一段批處理程序需要被執(zhí)行時,使用不同的策略進行測試谐鼎,使用速度最快的那一種舰蟆。
- 對于批處理程序,考慮使用Tiered編譯方式作為默認(rèn)選項狸棍。
長時間運行應(yīng)用的優(yōu)化
對于長時間運行的應(yīng)用身害,比如Servlet程序等,一般會使用吞吐量來測試它們的性能草戈。 以下的一組數(shù)據(jù)表示了一個典型的數(shù)據(jù)獲取程序在使用不同“熱身時間”以及不同編譯策略時塌鸯,對吞吐量(OPS)的影響(執(zhí)行時間為60s):
Warm-upPeriod | -client | -server | -XX:+TieredCompilation |
---|---|---|---|
0s | 15.87 | 23.72 | 24.23 |
60s | 16.00 | 23.73 | 24.26 |
300s | 16.85 | 24.42 | 24.43 |
即使當(dāng)“熱身時間”為0秒,因為執(zhí)行時間為60秒唐片,所以編譯器也有機會在次期間做出優(yōu)化丙猬。
從上面的數(shù)據(jù)可以發(fā)現(xiàn)的幾個結(jié)論:
- 對于典型的數(shù)據(jù)獲取程序,編譯器對代碼編譯和優(yōu)化發(fā)生的十分迅速费韭,當(dāng)“熱身時間”顯著增加時茧球,如從60秒增加到300秒,最后得到的OPS差異并不明顯星持。
- -server JIT編譯器和Tiered編譯的性能顯著優(yōu)于-client JIT編譯器袜腥。
總結(jié)
- 對于長時間運行的應(yīng)用,總是使用-server JIT編譯器或者Tiered編譯策略。
代碼緩存調(diào)優(yōu)(Tuning the Code Cache)
當(dāng)JVM對代碼進行編譯后羹令,被編譯的代碼以匯編指令的形式存在于代碼緩存中(Code Cache)鲤屡,顯然這個緩存區(qū)域也是有大小限制的,當(dāng)此區(qū)域被填滿了之后福侈,編譯器就不能夠再編譯其他Java字節(jié)碼了酒来。
Code Cache的最大空間可以通過:-XX:ReservedCodeCacheSize=N來進行設(shè)置。
4 JVM線程調(diào)優(yōu)
調(diào)節(jié)線程棧大小
通過設(shè)置-Xss參數(shù)肪凛,在內(nèi)存比較稀缺的機器上堰汉,可以減少線程棧的大小,在32位的JVM上伟墙,可以減少線程棧大小翘鸭,可以稍稍增加堆的可用內(nèi)存。每個線程默認(rèn)會開啟1M的堆棧戳葵,用于存放棧幀就乓、調(diào)用參數(shù)、局部變量等拱烁,對大多數(shù)應(yīng)用而言這個默認(rèn)值太了生蚁,一般256K就足用。
偏向鎖
使用-XX:UseBiasedLocking選項來禁用偏向鎖戏自,偏向鎖默認(rèn)開啟邦投。偏向鎖可以提高緩存命中率,但是因為偏向鎖也需要一些簿記信息擅笔,有時候性能會更糟志衣,比如使用了某些線程池,同步資源或代碼一直都是多線程訪問的猛们,那么消除偏向鎖這一步驟對你來說就是多余的蠢涝。
自旋鎖
使用-XX:UseSpinning參數(shù)可以設(shè)置自旋鎖是否開啟,但是Java7以后自旋鎖無法禁用阅懦。
線程優(yōu)先級
每個線程都可以由開發(fā)人員指定優(yōu)先級和二,不過真正執(zhí)行時的優(yōu)先級還取決于操作系統(tǒng)為每個線程計算的當(dāng)前優(yōu)先級。開發(fā)人員不能依賴線程優(yōu)先級來影響其性能耳胎,如果要提高某些任務(wù)的優(yōu)先級惯吕,就必須使用應(yīng)用層邏輯來劃分優(yōu)先級,可以通過將任務(wù)指派給不同線程池并修改哪些池子大小來實現(xiàn)怕午。
總結(jié)
理解線程如何運作废登,可以獲得很大的性能優(yōu)勢,不過就線程的性能而言郁惜,沒有太多可以調(diào)優(yōu)的:可以修改的JVM標(biāo)識相當(dāng)少堡距,而且效果不明顯。
5 典型案例
$JAVA_ARGS
.=
"
-Dresin.home=$SERVER_ROOT
-server
-Xmx3000M
-Xms3000M
-Xmn600M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-Xss256K
-XX:+DisableExplicitGC
-XX:SurvivorRatio=1
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled
-XX:LargePageSizeInBytes=128M
-XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log
";
說明:
64位jdk參考設(shè)置,年老代漲得很慢羽戒,CMS執(zhí)行頻率變小缤沦,CMS沒有停滯,也不會有promotion failed問題易稠,內(nèi)存回收得很干凈
個人介紹:
高廣超 :多年一線互聯(lián)網(wǎng)研發(fā)與架構(gòu)設(shè)計經(jīng)驗缸废,擅長設(shè)計與落地高可用、高性能互聯(lián)網(wǎng)架構(gòu)驶社。