Jmeter性能测试-GC相关
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
https://www.cnblogs.com/danqiu/p/6009016.html
?
Jmeter性能測(cè)試-GC相關(guān)
1.GC相關(guān)
HotSpot虛擬機(jī)將其物理上劃分為兩個(gè)–新生代(young generation)和老年代(old generation)。
新生代(Young generation):?絕大多數(shù)最新被創(chuàng)建的對(duì)象會(huì)被分配到這里,由于大部分對(duì)象在創(chuàng)建后會(huì)很快變得不可到達(dá),所以很多對(duì)象被創(chuàng)建在新生代,然后消失。對(duì)象從這個(gè)區(qū)域消失的過程我們稱之為”minor GC“。
老年代(Old generation):?對(duì)象沒有變得不可達(dá),并且從新生代中存活下來,會(huì)被拷貝到這里。其所占用的空間要比新生代多。也正由于其相對(duì)較大的空間,發(fā)生在老年代上的GC要比新生代少得多。對(duì)象從老年代中消失的過程,我們稱之為”major GC“(或者”full GC“)
圖中的持久代(?permanent generation?)也被稱為方法區(qū)(method area)。他用來保存類常量以及字符串常量。因此,這個(gè)區(qū)域不是用來永久的存儲(chǔ)那些從老年代存活下來的對(duì)象。這個(gè)區(qū)域也可能發(fā)生GC。并且發(fā)生在這個(gè)區(qū)域上的GC事件也會(huì)被算為major GC。
新生代是用來保存那些第一次被創(chuàng)建的對(duì)象,他可以被分為三個(gè)空間
- ?一個(gè)伊甸園空間(Eden?)
- ?兩個(gè)幸存者空間(Survivor?)
- 絕大多數(shù)剛剛被創(chuàng)建的對(duì)象會(huì)存放在伊甸園空間。
- 在伊甸園空間執(zhí)行了第一次GC之后,存活的對(duì)象被移動(dòng)到其中一個(gè)幸存者空間。
- ? 此后,在伊甸園空間執(zhí)行GC之后,存活的對(duì)象會(huì)被堆積在同一個(gè)幸存者空間。
- ?當(dāng)一個(gè)幸存者空間飽和,還在存活的對(duì)象會(huì)被移動(dòng)到另一個(gè)幸存者空間。之后會(huì)清空已經(jīng)飽和的那個(gè)幸存者空間。
- 在以上的步驟中重復(fù)幾次依然存活的對(duì)象,就會(huì)被移動(dòng)到老年代。
jstat 是HotSpot JVM提供的一個(gè)監(jiān)控工具
jstat –gc? $<pid$> 1000
?
S0C?????? S1C?????? S0U??? S1U????? EC???????? EU????????? OC???????? OU???????? PC???????? PU???????? YGC???? YGCT??? FGC????? FGCT???? GCT
3008.0?? 3072.0??? 0.0???? 1511.1?? 343360.0?? 46383.0???? 699072.0?? 283690.2?? 75392.0??? 41064.3??? 2540??? 18.454??? 4????? 1.133??? 19.588
3008.0?? 3072.0??? 0.0???? 1511.1?? 343360.0?? 47530.9???? 699072.0?? 283690.2?? 75392.0??? 41064.3??? 2540??? 18.454??? 4????? 1.133??? 19.588
3008.0?? 3072.0??? 0.0???? 1511.1?? 343360.0?? 47793.0???? 699072.0?? 283690.2?? 75392.0??? 41064.3??? 2540??? 18.454??? 4????? 1.133??? 19.588
?
這些信息很重要,因?yàn)樗鼈冋故玖薌C處理到底花費(fèi)了多少時(shí)間。
在這個(gè)例子中,YGC 是217而YGCT 是0.928,這樣在簡單的計(jì)算數(shù)據(jù)平均數(shù)后,你可以知道每次新生代的GC大概需要4ms(0.004秒),而full GC的平均時(shí)間為33ms。
但是,只看數(shù)據(jù)平均數(shù)經(jīng)常無法分析出真正的GC問題。這是主要是因?yàn)镚C操作時(shí)間嚴(yán)重的偏差(換句話說,假如兩次full GC的時(shí)間是 67ms,那么其中的一次full GC可能執(zhí)行了10ms而另一個(gè)可能執(zhí)行了57ms。)為了更好地檢測(cè)每次GC處理時(shí)間,最好使用 –verbosegc來替代數(shù)據(jù)平均數(shù)。
為什么需要優(yōu)化GC
或者說的更確切一些,對(duì)于基于Java的服務(wù),是否有必要優(yōu)化GC?應(yīng)該說,對(duì)于所有的基于Java的服務(wù),并不總是需要進(jìn)行GC優(yōu)化,但前提是所運(yùn)行的基于Java的系統(tǒng),包含了如下參數(shù)或行為:
- 已經(jīng)通過?-Xms?和–Xmx 設(shè)置了內(nèi)存大小
- 包含了?-server?參數(shù)
- 系統(tǒng)中沒有超時(shí)日志等錯(cuò)誤日志
換句話說,如果你沒有設(shè)定內(nèi)存的大小,并且系統(tǒng)充斥著大量的超時(shí)日志時(shí),你就需要在你的系統(tǒng)中進(jìn)行GC優(yōu)化了。
但是,你需要時(shí)刻銘記一條:GC優(yōu)化永遠(yuǎn)是最后一項(xiàng)任務(wù)。
我為GC優(yōu)化歸納了兩個(gè)目的:
?
將轉(zhuǎn)移到老年代的對(duì)象數(shù)量降到最少
按代的GC機(jī)制由Oracle JVM提供,不包括可以在JDK7以及更高版本中使用的G1 GC。換句話說,對(duì)象被創(chuàng)建在伊甸園空間,而后轉(zhuǎn)化到幸存者空間,最終剩余的對(duì)象被送到老年代。某些比較大的對(duì)象會(huì)在被創(chuàng)建在伊甸園空間后,直接轉(zhuǎn)移到老 年代空間。老年代空間上的GC處理會(huì)新生代花費(fèi)更多的時(shí)間。因此,減少被移到老年代對(duì)象的數(shù)據(jù)可以顯著地減少Full GC的頻率。減少被移到老年代空間的對(duì)象的數(shù)量,可能被誤解為將對(duì)象留在新生代。但是,這是不可能的。取而代之,你可以調(diào)整新生代空間的大小。
減少Full GC執(zhí)行時(shí)間
Full GC的執(zhí)行時(shí)間比Minor GC要長很多。因此,如果Full GC花費(fèi)了太多的時(shí)間(超過1秒),一些連接的部分可能會(huì)發(fā)生超時(shí)錯(cuò)誤。
- 如果你試圖通過消減老年代空間來減少Full GC的執(zhí)行時(shí)間,可能會(huì)導(dǎo)致OutOfMemoryError?或者 Full GC執(zhí)行的次數(shù)會(huì)增加。
- 與之相反,如果你試圖通過增加老年代空間來減少Full GC執(zhí)行次數(shù),執(zhí)行時(shí)間會(huì)增加。
因此,你需要將老年代空間設(shè)定為一個(gè)“合適”的值。
影響GC性能的參數(shù)
正如我們?cè)诘诙恼陆Y(jié)尾提到的,不要幻想“某個(gè)人設(shè)定了GC參數(shù)后性能得到極大的提高,我們?yōu)槭裁床缓退靡粯拥膮?shù)?”,因?yàn)椴煌腤eb服務(wù)所創(chuàng)建對(duì)象的大小和他們的生命周期都不盡相同。
簡單來說,如果一個(gè)任務(wù)的執(zhí)行條件是A,B,C,D和E,同樣的任務(wù)執(zhí)行條件換為A和B,你會(huì)覺得哪個(gè)更快?從一般人的直覺來看,在A和B條件下執(zhí)行的任務(wù)會(huì)更快。
Java GC參數(shù)也是相同的道理,設(shè)定一些參數(shù)不但沒有提高GC執(zhí)行速度,反而可能導(dǎo)致他更慢。GC優(yōu)化的最基本原則是將不同的GC參數(shù)用于2臺(tái)或者多臺(tái)服務(wù)器,并進(jìn)行對(duì)比,并將那些被證明提高了性能或者減少了GC執(zhí)行時(shí)間的參數(shù)應(yīng)用于服務(wù)器。請(qǐng)謹(jǐn)記這一點(diǎn)。
下面這個(gè)表格列出了GC參數(shù)中與內(nèi)存大小相關(guān)的,可以影響性能的參數(shù)。
表1:GC優(yōu)化需要考慮的Java參數(shù)
| 定義 | 參數(shù) | 描述 |
| 堆內(nèi)存空間 | -Xms | Heap area size when starting JVM 啟動(dòng)JVM時(shí)的堆內(nèi)存空間。 |
| ? | -Xmx | Maximum heap area size 堆內(nèi)存最大限制 |
| 新生代空間 | -XX:NewRatio | Ratio of New area and Old area 新生代和老年代的占比 |
| ? | -XX:NewSize | New area size 新生代空間 |
| ? | -XX:SurvivorRatio | Ratio ofEdenarea and Survivor area 伊甸園空間和幸存者空間的占比 |
我在進(jìn)行GC優(yōu)化時(shí)經(jīng)常使用-Xms,-Xmx和-XX:NewRatio。-Xms和-Xmx是必須的。你如何設(shè)定NewRatio?會(huì)對(duì)GC性能產(chǎn)生十分顯著的影響。有些人可能會(huì)問如何設(shè)定Perm區(qū)域的大小?你可以通過-XX:PermSize?和-XX:MaxPermSize參數(shù)來設(shè)定,
當(dāng)OutOfMemoryError?錯(cuò)誤發(fā)生并且是由于Perm空間不足導(dǎo)致時(shí),另一個(gè)可能影響GC性能的參數(shù)是GC類型。下表列出了所有可選的GC類型(基于JDK6.0)
在分析監(jiān)控結(jié)果后,決定是否進(jìn)行GC優(yōu)化
在檢查GC狀態(tài)的過程中,你應(yīng)該分析監(jiān)控結(jié)果以便決定是否進(jìn)行GC優(yōu)化,如果分析結(jié)果表明執(zhí)行GC的時(shí)間只有0.1-0.3秒,那你就沒必要浪費(fèi)時(shí)間去進(jìn)行GC優(yōu)化。但是,如果GC的執(zhí)行時(shí)間是1-3秒,或者超過10秒,GC將勢(shì)在必行。
但是,如果你已經(jīng)為Java分配了10GB的內(nèi)存,并且不能再減少內(nèi)存大小,你將無法再對(duì)GC進(jìn)行優(yōu)化。在進(jìn)行GC優(yōu)化 之前,你必須想清楚你為什么要分配如此大的內(nèi)存空間。假如當(dāng)你分1 GB 或 2 GB內(nèi)存時(shí)出現(xiàn)OutOfMemoryError?,你應(yīng)該執(zhí)行堆內(nèi)存轉(zhuǎn)儲(chǔ)(heap dump),并消除隱患。
注意:
堆內(nèi)存轉(zhuǎn)儲(chǔ)是一個(gè)用來檢查Java內(nèi)存中的對(duì)象和數(shù)據(jù)的文件。該文件可以通過執(zhí)行JDK中的jmap命令來創(chuàng)建。在創(chuàng)建文件的過程中,Java程序會(huì)暫停,因此不要再系統(tǒng)執(zhí)行過程中創(chuàng)建該文件。
如果GC執(zhí)行時(shí)間滿足下面所有的條件,就意味著無需進(jìn)行GC優(yōu)化了。
- Minor GC執(zhí)行的很快(小于50ms)
- Minor GC執(zhí)行的并不頻繁(大概10秒一次)
- Full GC執(zhí)行的很快(小于1s)
- Full GC執(zhí)行的并不頻繁(10分鐘一次)
上面提到的數(shù)字并不是絕對(duì)的;他們根據(jù)服務(wù)狀態(tài)的不同而有所區(qū)別,某些服務(wù)可能滿足于Full GC每次0.9秒的速度,但另一些可能不是。因此,針對(duì)不同的服務(wù)設(shè)定不同的值以決定是否進(jìn)行GC優(yōu)化。
- 設(shè)定內(nèi)存空間大小
下表展示了內(nèi)存空間大小,GC執(zhí)行次數(shù)以及GC執(zhí)行時(shí)間三者間的關(guān)系。
-
- 大內(nèi)存空間
- 減小GC執(zhí)行次數(shù)
- 增加GC執(zhí)行時(shí)間
- 小內(nèi)存空間
- 減小GC執(zhí)行時(shí)間
- 增加GC執(zhí)行次數(shù)
- 大內(nèi)存空間
關(guān)于如何設(shè)置內(nèi)存空間的大小,沒有唯一的標(biāo)準(zhǔn)答案。如果服務(wù) 器資源足夠,而且Full GC也可能在1秒內(nèi)完成,設(shè)置為10GB當(dāng)然可行。。但絕大多數(shù)服務(wù)器并不是這樣,當(dāng)內(nèi)存設(shè)為10GB時(shí),可能要花費(fèi)10~30秒來執(zhí)行Full GC。當(dāng)然,執(zhí)行時(shí)間會(huì)隨對(duì)象的大小而改變。
鑒于如此,我們應(yīng)該如何設(shè)定內(nèi)存空間大小呢?一 般來說,我建議為500MB。不過請(qǐng)注意這不是讓你將WAS的內(nèi)存參數(shù)設(shè)置為–Xms500m?和–Xmx500m。根據(jù)優(yōu)化GC之前的狀態(tài),如果 Full GC執(zhí)行之后內(nèi)存空間剩余300MB,那么最好將內(nèi)存設(shè)置為1GB(300MB(默認(rèn)程序占用)+ 500MB(老年代最小空間)+200MB(空閑內(nèi)存))。也就是說你要為老年代額外設(shè)置500MB。因此,如果你有三個(gè)執(zhí)行服務(wù)器,內(nèi)存分別設(shè)置為 1GB,1.5GB,2GB,并且檢查結(jié)果。
理論上來講,GC執(zhí)行速度應(yīng)該遵循1GB> 1.5GB> 2GB,因此1GB執(zhí)行GC速度最快。但是并不說明1GB空間的Full GC會(huì)花費(fèi)1秒而2GB空間會(huì)花費(fèi)2秒。時(shí)間取決于服務(wù)器的性能和對(duì)象的大小。因此,最佳的方式是建立盡可能多的衡量指標(biāo)來監(jiān)控他們。
對(duì)于內(nèi)存空間大小,你應(yīng)該額外設(shè)定NewRatio參數(shù)。 NewRatio參數(shù)是新生代和老年代空間的比例,即XX:NewRatio=1意味著新生代與老年代之比為1:1。對(duì)于1GB來說就是新生代和老年代各 500MB。如果NewRatio為2,意味著新生代老年代之比為1:2,因此該值越大,老年代空間越大,新生代空間越小。
這看似一件不是很重要的事情,但NewRatio參數(shù)會(huì)顯著地影響整個(gè)GC的性能。如果新生代空間很小,會(huì)用更多的對(duì)象被轉(zhuǎn)移到老年代空間,這樣導(dǎo)致頻繁的Full GC,增加暫停時(shí)間。
你可以簡單的認(rèn)為NewRatio 為1是最佳的選擇,但是,有時(shí)可能設(shè)置為2或3更好,我就見過很多這樣的例子。
如何最快的完成GC優(yōu)化?對(duì)比性能測(cè)試的結(jié)果 應(yīng)該是最快地方法,為每一臺(tái)服務(wù)器設(shè)置不同的參數(shù)并監(jiān)控他們的狀態(tài),強(qiáng)烈建議至少監(jiān)控1或2天的數(shù)據(jù)。但是,當(dāng)你對(duì)GC優(yōu)化是,你要確保每次執(zhí)行相同的負(fù) 載。并且請(qǐng)求的比率,例如URL都應(yīng)該是一致的。不過,即便對(duì)于專業(yè)測(cè)試人員要想精確的控制負(fù)載也是很難的,并要花費(fèi)大量的時(shí)間準(zhǔn)備。因此,相對(duì)來說比較 方便和容易的方法是調(diào)整才參數(shù),之后花費(fèi)較長的時(shí)間收集結(jié)果。?
示例1
下面這個(gè)例子針對(duì)?Service S的優(yōu)化,對(duì)于最近被部署的?Service S,Full GC花費(fèi)了太長的時(shí)間。
請(qǐng)看?jstat –gcutil的執(zhí)行結(jié)果。
?
| 1 2 | S0 S1 E O P YGC YGCT FGC FGCT GCT 12.16?0.00?5.18?63.78?20.32?54?2.047?5?6.946?8.993 |
?
最左邊的Perm?空間對(duì)于最初的GC優(yōu)化不是很重要,這一次YGC參數(shù)的值更加有用。
Minor GC和Full GC的平均值如下表所示
表3:Service S的Minor GC?和Full GC的平均執(zhí)行時(shí)間
| GC 類型 | GC 執(zhí)行次數(shù) | GC 執(zhí)行時(shí)間 | 平均 |
| Minor GC | 54 | 2.047 | 37 ms |
| Full GC | 5 | 6.946 | 1,389 s |
最重要的是下面兩個(gè)數(shù)據(jù)
- 新生代實(shí)際使用空間: 212,992 KB
- 老年代實(shí)際使用空間: 1,884,160 KB
因此,總的內(nèi)存空間為2GB,不算Perm空間的話,新生代與老年代之比為1:9。通過jstat和-verbosegc?日志進(jìn)行數(shù)據(jù)收集,并把三臺(tái)服務(wù)器按照如下方式設(shè)置。
- NewRatio=2
- NewRatio=3
- NewRatio=4
一天之后,檢查系統(tǒng)的GC日志后發(fā)現(xiàn),在設(shè)置了NewRatio參數(shù)后很幸運(yùn)的沒有發(fā)生Full GC,
為什么?
- NewRatio=2: 45 ms
- NewRatio=3: 34 ms
- NewRatio=4: 30 ms
我們看到NewRatio=4 是最佳的參數(shù),雖然它的新生代空間最小,但GC時(shí)間確最短。設(shè)定這個(gè)參數(shù)之后,系統(tǒng)沒有執(zhí)行過Full GC。
為了說明這個(gè)問題,下面是服務(wù)之星一段時(shí)間后執(zhí)行jstat –gcutil的結(jié)果
?
| 1 2 | S0 S1 E O P YGC YGCT FGC FGCT GCT 8.61?0.00?30.67?24.62?22.38?2424?30.219?0?0.000?30.219 |
?
你可能會(huì)認(rèn)為因?yàn)榉?wù)器接受的請(qǐng)求少才導(dǎo)致的GC執(zhí)行頻率下降。實(shí)際上,雖然Full GC沒有執(zhí)行,但是Minor GC被執(zhí)行了 2,424次。
示例2
這是一個(gè)針對(duì)ServiceA的例子,我們通過公司內(nèi)部的應(yīng)用性能管理系統(tǒng)(APM)發(fā)現(xiàn)JVM暫停了相當(dāng)長的時(shí)間(超過8秒),因此我們進(jìn)行了GC優(yōu)化。我們找到了Full GC執(zhí)行時(shí)間過長的原因,并著手解決。
進(jìn)行GC優(yōu)化的第一步,就是我們添加了-verbosegc參數(shù),并得到如下結(jié)果。
圖1:進(jìn)行GC優(yōu)化之前的STW時(shí)間
如上圖所示,由HPJMeter自動(dòng)生成的圖片之一。X坐標(biāo)表示JVM執(zhí)行的時(shí)間。Y坐標(biāo)表示每次GC的時(shí)間。CMS綠點(diǎn),表示Full GC結(jié)果。Parallel Scavenge藍(lán)點(diǎn),表示Minor GC結(jié)果。
之前我曾經(jīng)說過CMS GC是最快的,但是上面的的結(jié)果顯示出于某種原因,它最多花費(fèi)了15秒。是什么導(dǎo)致這個(gè)結(jié)果?是否想起我之前提過的,CMS在進(jìn)行內(nèi)存清理時(shí),會(huì)變慢。與此同時(shí),服務(wù)的內(nèi)存被設(shè)定為?–Xms1g和–Xmx4g?,且實(shí)際分配了4GB內(nèi)存。
因此,我將GC類型從CMS改為Parallel GC。并且將內(nèi)存改為2GB,設(shè)定NewRatio?為3。幾小時(shí)之后我使用?jstat –gcutil得到如下結(jié)果
?
| 1 2 | S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00?30.48?3.31?26.54?37.01?226?11.131?4?11.758?22.890 |
?
相對(duì)于4GB時(shí)的15秒,Full GC變成了平均每次3秒。但是3秒一樣比較慢,因此我設(shè)計(jì)了如下6種場(chǎng)景。
- Case 1:?-XX:+UseParallelGC -Xms1536m -Xmx1536m -XX:NewRatio=2
- Case 2:?-XX:+UseParallelGC -Xms1536m -Xmx1536m -XX:NewRatio=3
- Case 3:?-XX:+UseParallelGC -Xms1g -Xmx1g -XX:NewRatio=3
- Case 4:?-XX:+UseParallelOldGC -Xms1536m -Xmx1536m -XX:NewRatio=2
- Case 5:?-XX:+UseParallelOldGC -Xms1536m -Xmx1536m -XX:NewRatio=3
- Case 6:?-XX:+UseParallelOldGC -Xms1g -Xmx1g -XX:NewRatio=3
那一個(gè)最快呢?結(jié)果顯示,內(nèi)存越小,結(jié)果越好。下圖展示了Case6的結(jié)果。這是GC的性能最好。最長的響應(yīng)時(shí)間只有1.7秒。平均時(shí)間在1秒之內(nèi)。
圖2:Case6的時(shí)間圖表
基于以上結(jié)果。我們按照Case6調(diào)整了GC參數(shù)。但是,這導(dǎo)致了每天晚上都會(huì)發(fā)生OutOfMemoryError。在這里很難解釋具體的原因。簡單來說,批處理程序?qū)е铝藘?nèi)存泄漏。相關(guān)的問題已經(jīng)被解決。
如果對(duì)GC日志只分析很短的時(shí)間就貿(mào)然對(duì)所有服務(wù)器進(jìn)行優(yōu)化是非常危險(xiǎn)的。請(qǐng)時(shí)刻牢記,你必須同時(shí)分析GC日志和應(yīng)用程序。
我們回顧了兩個(gè)關(guān)于GC優(yōu)化的例子,正如我之前提到的,例子中提到的GC參數(shù),可以設(shè)置在相同的服務(wù)器之上,但前提是他們具有相同的CPU,操作系統(tǒng),JDK版本以及運(yùn)行著相同的服務(wù)。但是不要直接把我用過的參數(shù)用到你的服務(wù)至上,它們未必能很好的工作。
?
切實(shí)地調(diào)優(yōu)
如果測(cè)試的結(jié)果滿足了預(yù)期,那么你不需要對(duì)程序進(jìn)行性能調(diào)優(yōu)。如果沒有達(dá)到預(yù)期結(jié)果,你就應(yīng)該執(zhí)行調(diào)優(yōu)來解決問題。接下來會(huì)通過實(shí)例講解方法。
stop-the-world耗時(shí)過長
stop-the-world耗時(shí)過長可能是由于GC參數(shù)不合理或者代碼實(shí)現(xiàn)不正確。你可以通過分析工具或堆內(nèi)存轉(zhuǎn)儲(chǔ)文件(Heap dump)來定位問題,比如檢查堆內(nèi)存中對(duì)象的類型和數(shù)量。如果在其中找到了很多不必要的對(duì)象,那么最好去改進(jìn)代碼。如果沒有發(fā)現(xiàn)創(chuàng)建對(duì)象的過程中有特別 的問題,那么最好單純地修改GC參數(shù)。
為了適當(dāng)?shù)卣{(diào)整GC參數(shù),你需要獲取一段足夠長時(shí)間的GC日志,還必須知道哪些情況會(huì)導(dǎo)致長時(shí)間的stop-the-world。想了解更多關(guān)于如何選擇合適的GC參數(shù),可以閱讀我同事的一篇博文:How to Monitor Java Garbage Collection。
CPU使用率過低
當(dāng)系統(tǒng)發(fā)生阻塞,吞吐量和CPU使用率都會(huì)降低。這可能是由于網(wǎng)絡(luò)系統(tǒng)或者并發(fā)的問題。為了解決這個(gè)問題,你可以分析線程轉(zhuǎn)儲(chǔ)信息(Thread dump)或者使用分析工具。閱讀這篇文章可以獲得更多關(guān)于線程轉(zhuǎn)儲(chǔ)分析的知識(shí):How to Analyze Java Thread Dumps。
你可以使用商業(yè)的分析工具對(duì)線程鎖進(jìn)行精確的分析,不過大部分時(shí)候,只需使用JVisualVM中的CPU分析器,就能獲得足夠的信息。
CPU使用率過高
如果吞吐量很低但是CPU使用率卻很高,很可能是低效率代碼導(dǎo)致的。這種情況下,你應(yīng)該使用分析工具定位代碼中性能的瓶頸。可使用的工具有:JVisualVM、Eclipse?TPTP或者JProbe。
調(diào)優(yōu)方法
建議你使用如下方法對(duì)程序進(jìn)行調(diào)優(yōu)。
首先,檢查性能調(diào)優(yōu)是否必要。測(cè)量性能不是一件簡單的工作,你也不能保證每次都獲得滿意的結(jié)果。因此如果程序已經(jīng)滿足預(yù)期性能需求,不必在調(diào)優(yōu)上增加額外的投入了。
問題只出在一個(gè)地方,你要做的就是去解決掉它。二八定律(Pareto principle)對(duì)性能調(diào)優(yōu)同樣適用。這不是說某個(gè)模塊的低性能一定只源于一個(gè)問題,而是強(qiáng)調(diào)我們應(yīng)該在調(diào)優(yōu)時(shí)把注意力放在影響最大的那個(gè)問題上。在處理好了最重要的之后,你才應(yīng)該去解決剩下其他的。也就是建議一次只對(duì)一個(gè)問題進(jìn)行修復(fù)。
另外需要考慮到氣球效應(yīng)(Balloon effect),有得必有失。你可以通過使用緩存來提高響應(yīng)能力,但是當(dāng)緩存逐漸增大,執(zhí)行一次Full GC的時(shí)間也會(huì)更長。一般而言,如果你希望內(nèi)存使用率比較低,那么吞吐量和響應(yīng)能力可能都會(huì)惡化。因此,要知道什么對(duì)自己程序來說最重要的,而哪些又是次要的。
到此為止,你應(yīng)該已經(jīng)了解了如何對(duì)Java程序進(jìn)行性能調(diào)優(yōu)。為了介紹性能測(cè)定的具體過程,我不得不省略其中一些細(xì)節(jié),不過我認(rèn)為這些也足夠應(yīng)對(duì)大多數(shù)Java Web服務(wù)端程序了
?
2.操作相關(guān)
1.如何考慮一個(gè)性能需求
1.?通常拿到一個(gè)性能需求,需要了解接口模型,整個(gè)接口的使用比例和容量,系統(tǒng)結(jié)構(gòu)和技術(shù)方案,數(shù)據(jù)庫緩存和索引分布,設(shè)計(jì)出合理的測(cè)試計(jì)劃,設(shè)計(jì)的原則是盡可能真實(shí)的模擬線上情況。
2.根據(jù)設(shè)計(jì)出的測(cè)試計(jì)劃,使用一個(gè)線程運(yùn)行測(cè)試計(jì)劃,得出測(cè)試結(jié)果,對(duì)比測(cè)試指標(biāo)
3.以線性增長的方式增加并發(fā)數(shù),比較測(cè)試結(jié)果是否為線性增長
4.測(cè)試結(jié)果平緩區(qū)通常代表著系統(tǒng)容量的最大區(qū)域,分析此時(shí)的測(cè)試結(jié)果,如 TPS和響應(yīng)時(shí)間等
5.分析數(shù)據(jù)庫TPS、QPS等數(shù)據(jù),redis命中率,MQ吞吐率,javaGC,程序占用時(shí)間等各方面因素提高系統(tǒng)性能
6.通過jstack分析各模塊的資源占用情況。
7.優(yōu)化后的程序要經(jīng)過大批量數(shù)據(jù)測(cè)試確保測(cè)試程序不會(huì)發(fā)生錯(cuò)誤
8.根據(jù)測(cè)試概要報(bào)告,數(shù)據(jù)庫監(jiān)控?cái)?shù)據(jù)等數(shù)據(jù)整合測(cè)試報(bào)告
9. 需要關(guān)注api層用的是長連接還是短連接,長連接的話需要在jmeter里勾選keep alive
2.如何保證jmeter自身性能
1.使用命令行啟動(dòng),減少界面造成的性能問題
2.命令行記錄聚合報(bào)告,不要啟動(dòng)過多的其他監(jiān)控報(bào)告
3.盡可能關(guān)閉不必要的日志,包括測(cè)試代碼的log,jmeter自身日志。
4.確保測(cè)試腳本計(jì)時(shí)準(zhǔn)確,需確認(rèn)好那些步驟需要計(jì)時(shí),那些在準(zhǔn)備在計(jì)時(shí)之外
5.過多的并發(fā)使用分布式請(qǐng)求,當(dāng)本地cpu,mem占用比較大時(shí),修改jmeter.properties,增加遠(yuǎn)程remote-server,并啟動(dòng)(具體操作見jmeter操作手冊(cè))
3.如何分析測(cè)試結(jié)果
1.根據(jù)聚合報(bào)告分析90%,95%,和最大等指標(biāo),找出程序普遍的響應(yīng)時(shí)間。
2.讓開發(fā)人員查詢最大響應(yīng)時(shí)間時(shí)的日志,分析程序?qū)用娴膱?zhí)行任務(wù)情況
3.使用jstack等分析當(dāng)前程序的資源等待情況,系統(tǒng)資源情況
值得關(guān)注的線程狀態(tài)有:
?????死鎖,Deadlock(重點(diǎn)關(guān)注)
?????執(zhí)行中,Runnable??
?????等待資源,Waiting on condition(重點(diǎn)關(guān)注)
?????等待獲取監(jiān)視器,Waiting on monitor entry(重點(diǎn)關(guān)注)
?????暫停,Suspended
?????對(duì)象等待中,Object.wait() 或 TIMED_WAITING
?????阻塞,Blocked(重點(diǎn)關(guān)注)?
?????停止,Parked
示例圖
4.分析gc結(jié)果,cpu,IO等情況,分析程序是否充分利用了系統(tǒng)資源
5.對(duì)比分析各并發(fā)數(shù)的程序響應(yīng)情況。
分類:?性能測(cè)試
轉(zhuǎn)載于:https://my.oschina.net/u/3160044/blog/2966729
總結(jié)
以上是生活随笔為你收集整理的Jmeter性能测试-GC相关的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA入门到精通-第43讲-IO编程-
- 下一篇: Linux下防火墙开放端口