?摘自:https://help.aliyun.com/document_detail/29342.html?spm=5176.doc29335.6.613.eyyyMZ
1 引言
1.1 編寫目的
本文通過編寫性能測試分析及調(diào)優(yōu)相關(guān)流程和方法懂衩,幫助性能測試人員很快的進行性能測試瓶頸定位及調(diào)優(yōu)。
系統(tǒng)的性能是由很多因素決定的惜犀,本文不可能將每種瓶頸和調(diào)優(yōu)說的非常清楚躬厌,但是可以指導(dǎo)怎么去分析系統(tǒng)的性能马昨。
1.2 適用對象和范圍
適用于使用性能測試進行性能測試項目性能分析及調(diào)優(yōu)依據(jù)。
預(yù)期讀者為測試管理人員扛施、測試實施人員鸿捧、技術(shù)支持人員、項目質(zhì)量管理人員疙渣、項目管理人員等系統(tǒng)技術(shù)質(zhì)量相關(guān)人員匙奴。
2 性能分析
2.1 前提
性能分析的前提是不僅需要性能測試人員有相關(guān)的技術(shù)知識(例如:操作系統(tǒng)、中間件妄荔、數(shù)據(jù)庫泼菌、開發(fā)等)谍肤,而且還需要豐富的性能測試監(jiān)控(請參照:性能測試監(jiān)控)。
2.2 流程
關(guān)鍵指標是否滿足要求灶轰,如果不滿足谣沸,需要確定是哪個地方有問題,一般情況下笋颤,服務(wù)器端問題可能性比較大,也有可能是客戶端問題(這種情況非常心诘亍)伴澄。
對于服務(wù)器端問題,需要定位的是硬件相關(guān)指標阱缓,例如CPU非凌,Memory, Disk I/O, Network I/O, 如果是某個硬件指標有問題,需要深入的進行分析荆针。
如果硬件指標都沒有問題敞嗡,需要查看中間件相關(guān)指標,例如:線程池航背、連接池喉悴、GC等,如果是這些指標問題玖媚,需要深入的 分析箕肃。
如果中間件相關(guān)指標沒問題,需要查看數(shù)據(jù)庫相關(guān)指標今魔,例如:慢查SQL勺像,命中率,鎖错森、參數(shù)設(shè)置吟宦。
如果以上指標都正常,應(yīng)用程序的算法涩维、緩沖殃姓、緩存、同步或異步可能有問題激挪,需要具體深入的分析辰狡。
具體如下圖所示:
2.3 可能瓶頸點
2.3.1 硬件上的性能瓶頸
一般指的是CPU、內(nèi)存垄分、磁盤I/O 方面的問題宛篇,分為服務(wù)器硬件瓶頸、網(wǎng)絡(luò)瓶頸(對局域網(wǎng)可以不考慮)薄湿、服務(wù)器操作系統(tǒng)瓶頸(參數(shù)配置)叫倍、中間件瓶頸(參數(shù)配置偷卧、數(shù)據(jù)庫、web服務(wù)器等)吆倦、應(yīng)用瓶頸(SQL 語句听诸、數(shù)據(jù)庫設(shè)計、業(yè)務(wù)邏輯蚕泽、算法等)晌梨。
2.3.2 中間件上的性能瓶頸
一般指的是應(yīng)用服務(wù)器、web 服務(wù)器等應(yīng)用軟件须妻,還包括數(shù)據(jù)庫系統(tǒng)仔蝌。
例如:中間件weblogic 平臺上配置的JDBC連接池的參數(shù)設(shè)置不合理,造成的瓶頸荒吏。
2.3.3 應(yīng)用程序上的性能瓶頸
一般指的是開發(fā)人員新開發(fā)出來的應(yīng)用程序敛惊。
例如,程序架構(gòu)規(guī)劃不合理绰更,程序本身設(shè)計有問題(串行處理瞧挤、請求的處理線程不夠、無緩沖儡湾、無緩存特恬、生產(chǎn)者和消費者不協(xié)調(diào)等),造成系統(tǒng)在大量用戶方位時性能低下而造成的瓶頸盒粮。
2.3.4 操作系統(tǒng)上的性能瓶頸
一般指的是windows鸵鸥、UNIX、Linux等操作系統(tǒng)丹皱。
例如妒穴,在進行性能測試,出現(xiàn)物理內(nèi)存不足時摊崭,虛擬內(nèi)存設(shè)置也不合理讼油,虛擬內(nèi)存的交換效率就會大大降低,從而導(dǎo)致行為的響應(yīng)時間大大增加呢簸,這時認為操作系統(tǒng)上出現(xiàn)性能瓶頸矮台。
2.3.5 網(wǎng)絡(luò)設(shè)備上的性能瓶頸
一般指的是防火墻、動態(tài)負載均衡器根时、交換機等設(shè)備瘦赫。
例如,在動態(tài)負載均衡器上設(shè)置了動態(tài)分發(fā)負載的機制蛤迎,當發(fā)現(xiàn)某個應(yīng)用服務(wù)器上的硬件資源已經(jīng)到達極限時确虱,動態(tài)負載均衡器將后續(xù)的交易請求發(fā)送到其他負載較輕的應(yīng)用服務(wù)器上。在測試時發(fā)現(xiàn)替裆,動態(tài)負載均衡器沒有起到相應(yīng)的作用校辩,這時可以認為網(wǎng)絡(luò)瓶頸窘问。
2.4 方法
2.4.1 CPU
CPU資源利用率很高的話,需要看CPU消耗User,Sys,Wait那種狀態(tài)下宜咒。
如果CPU User非常高惠赫,需要查看消耗在哪個進程,可以用top(linux)命令看出故黑,接著用top –H –p 看哪個線程消耗資源高儿咱,如果是java應(yīng)用,就可以用jstack看出此線程正在執(zhí)行的堆棧场晶,看資源消耗在哪個方法上概疆,查看源代碼就知道問題所在;如果是c++應(yīng)用峰搪,可以用gprof性能工具進行分析。
如果CPU Sys非常高凯旭,可以用strace(linux)看系統(tǒng)調(diào)用的資源消耗及時間概耻。
如果CPU Wait非常高,考慮磁盤讀寫了罐呼,可以通過減少日志輸出鞠柄、異步或換速度快的硬盤。
2.4.2 Memory
操作系統(tǒng)未了最大化利用內(nèi)存嫉柴,一般都設(shè)置大量的cache,因此厌杜,內(nèi)存利用率高達99%并不是問題,內(nèi)存的問題主要看某個進程占用的內(nèi)存是否非常大以及是否有大量的swap(虛擬內(nèi)存交換)计螺。
2.4.3 磁盤I/O
磁盤I/O一個最顯著的指標是繁忙率夯尽,可以通過減少日志輸出、異步或換速度快的硬盤登馒。
2.4.4 網(wǎng)絡(luò)I/O
網(wǎng)絡(luò)I/O主要考慮傳輸內(nèi)容大小匙握,不能超過硬件網(wǎng)絡(luò)傳輸?shù)淖畲笾?0%,可以通過壓縮陈轿、減少內(nèi)容大小圈纺、在本地設(shè)置緩存以及分多次傳輸?shù)取?/p>
2.4.5 內(nèi)核參數(shù)
內(nèi)核參數(shù)一般都有默認值,這些內(nèi)核參數(shù)默認值對于一般系統(tǒng)沒問題麦射,但是對于壓力測試來說蛾娶,可能運行的參數(shù)將會超過內(nèi)核參數(shù),導(dǎo)致系統(tǒng)出現(xiàn)問題潜秋,可以用sysctl來查看及修改蛔琅。
2.4.6 JVM
jvm主要分析GC/FULL GC是否頻繁,以及垃圾回收的時間半等,可以用jstat命令來查看揍愁,對于每個代大小以及GC頻繁呐萨,通過jmap將內(nèi)存dump,再借助工具HeapAnalyzer來分析哪地方占用的內(nèi)存較高以及是否有內(nèi)存泄漏可能。
2.4.7 線程池
如果線程不夠用莽囤,可以通過參數(shù)調(diào)整谬擦,增加線程;對于線程池中的線程設(shè)置比較大的情況朽缎,還是不夠用可能的原因是:某個線程被阻塞來不及釋放惨远,可能在等鎖、方法耗時較長话肖、數(shù)據(jù)庫等待時間很長等原因?qū)е卤被啵枰M一步分析才能定位。
2.4.8 JDBC連接池
連接池不夠用的情況下最筒,可以通過參數(shù)進行調(diào)整增加贺氓;但是對于數(shù)據(jù)庫本身處理很慢的情況下,調(diào)整沒有多大的效果床蜘,需要查看數(shù)據(jù)庫方面以及因代碼導(dǎo)致連接未釋放的原因辙培。
2.4.9 SQL
SQL效率低下也是導(dǎo)致性能差的一個非常重要的原因,可以通過查看執(zhí)行計劃看SQL慢在哪里邢锯,一般情況扬蕊,SQL效率低下原因主要有:
類別子類表達式或描述原因
索引未建索引產(chǎn)生全表掃描
未利用索引substring(card_no,1,4)=′5378′產(chǎn)生全表掃描
amount/30< 1000產(chǎn)生全表掃描
convert(char(10),date,112)=′19991201′產(chǎn)生全表掃描
where salary<>3000產(chǎn)生全表掃描
name like ‘%張’產(chǎn)生全表掃描
first_name + last_name ='beill cliton'產(chǎn)生全表掃描
id_no in(′0′,′1′)產(chǎn)生全表掃描
select id from t where num=@num有參數(shù)也會產(chǎn)生全表掃描
使用效能低的索引oder by 非聚族索引索引性能低
username='張三' and age>20字符串索引低于整形索引
表中列與空NULL值索引性能低
盡量不要使用IS NULL或IS NOT NULL索引性能低
數(shù)據(jù)量所有數(shù)據(jù)量select *很多列產(chǎn)生大量數(shù)據(jù)
select id,name表中有幾百萬行,產(chǎn)生大量數(shù)據(jù)
嵌套查詢先不過濾數(shù)據(jù),后過濾數(shù)據(jù)產(chǎn)生大量無用的數(shù)據(jù)
關(guān)聯(lián)查詢多表進行關(guān)聯(lián)查詢,先過濾掉小部分數(shù)據(jù)镐捧,在過濾大部分數(shù)據(jù)大量關(guān)聯(lián)操作
大數(shù)據(jù)量插入一次次插入產(chǎn)生大量日志漆羔,消耗資源
鎖鎖等待update account set banlance=100 where id=10產(chǎn)生表級鎖,將會鎖住整個表
死鎖A:update a;update b;B:update b;update a;將會產(chǎn)生死鎖
游標Cursor Open cursor,fetch;close cursor性能很低
臨時表create tmp table 創(chuàng)建臨時表產(chǎn)生大量日志
drop table刪除臨時表需要顯示刪除,避免系統(tǒng)表長時間鎖定
其他exist 代替 INselect num from a where num in(select num from b)in會逐個判斷,exist有一條就結(jié)束
exist 代替select count(*)判斷記錄是否存在count(*)將累加計算,exist有就結(jié)束
between 代替 INID in(1,2,3)IN逐個判斷,between是范圍判斷
left outer join 代替Not INselect ID from a where ID not in(select b.Mainid from b)NOT IN逐個判斷践磅,效率非常低
union all 代替unionselect ID from a union select id from b union刪除重復(fù)的行,可能會在磁盤進行排序而union all只是簡單的將結(jié)果并在一起
常用SQL盡量用綁定變量方法insert into A(ID) values(1)直接寫SQL每次都要編譯灸异,用綁定變量的方法只編譯一次府适,下次就可以用了
3 調(diào)優(yōu)
3.1 調(diào)優(yōu)步驟
3.1.1 確定問題
應(yīng)用程序代碼:在通常情況下,很多程序的性能問題都是寫出來的肺樟,因此對于發(fā)現(xiàn)瓶頸的模塊檐春,應(yīng)該首先檢查一下代碼。
數(shù)據(jù)庫配置:經(jīng)常引起整個系統(tǒng)運行緩慢么伯,一些諸如大型數(shù)據(jù)庫都是需要DBA進行正確的參數(shù)調(diào)整才能投產(chǎn)的疟暖。
操作系統(tǒng)配置:不合理就可能引起系統(tǒng)瓶頸。
硬件設(shè)置:硬盤速度、內(nèi)存大小等都是容易引起瓶頸的原因俐巴,因此這些都是分析的重點骨望。 網(wǎng)絡(luò):網(wǎng)絡(luò)負載過重導(dǎo)致網(wǎng)絡(luò)沖突和網(wǎng)絡(luò)延遲。
3.1.2 分析問題
當確定了問題之后欣舵,我們要明確這個問題影響的是響應(yīng)時間吞吐量擎鸠,還是其他問題?是多數(shù)用戶還是少數(shù)用戶遇到了問題缘圈?如果是少數(shù)用戶劣光,這幾個用戶與其它用戶的操作有什么不用?系統(tǒng)資源監(jiān)控的結(jié)果是否正常糟把?CPU的使用是否到達極限绢涡?I/O 情況如何?問題是否集中在某一類模塊中遣疯? 是客戶端還是服務(wù)器出現(xiàn)問題雄可? 系統(tǒng)硬件配置是否夠用?實際負載是否超過了系統(tǒng)的負載能力缠犀? 是否未對系統(tǒng)進行優(yōu)化滞项? 通過這些分析及一些與系統(tǒng)相關(guān)的問題,可以對系統(tǒng)瓶頸有更深入的了解夭坪,進而分析出真正的原因。
3.1.3 確定調(diào)整目標和解決方案
高系統(tǒng)吞吐量过椎,縮短響應(yīng)時間室梅,更好地支持并發(fā)。
3.1.4 測試解決方案
對通過解決方案調(diào)優(yōu)后的系統(tǒng)進行基準測試疚宇。(基準測試是指通過設(shè)計科學的測試方法亡鼠、測試工具和測試系統(tǒng),實現(xiàn)對一類測試對象的某項性能指標進行定量的和可對比的測試)敷待。
3.1.5 分析調(diào)優(yōu)結(jié)果
系統(tǒng)調(diào)優(yōu)是否達到或者超出了預(yù)定目標间涵?系統(tǒng)是整體性能得到了改善,還是以系統(tǒng)某部分性能來解決其他問題榜揖。調(diào)優(yōu)是否可以結(jié)束了勾哩。 最后,如果達到了預(yù)期目標举哟,調(diào)優(yōu)工作就基本可以結(jié)束了思劳。
3.2 調(diào)優(yōu)注意事項
在應(yīng)用系統(tǒng)的設(shè)計開發(fā)過程中,應(yīng)始終把性能放在考慮的范圍內(nèi)妨猩。
確定清晰明確的性能目標是關(guān)鍵潜叛。
必須保證調(diào)優(yōu)后的程序運行正確。
系統(tǒng)的性能更大程度上取決于良好的設(shè)計,調(diào)優(yōu)技巧只是一個輔助手段威兜。
調(diào)優(yōu)過程是迭代漸進的過程销斟,每一次調(diào)優(yōu)的結(jié)果都要反饋到后續(xù)的代碼開發(fā)中去。
性能調(diào)優(yōu)不能以犧牲代碼的可讀性和可維護性為代價