- 概述:Eclipse Test & Performance Tools Platform (TPTP) 的性能測試工具(Profiling tool)能夠用于優(yōu)化eclipse插件應(yīng)用、本地的java應(yīng)用,乃至是運(yùn)行在多臺不同平臺主機(jī)上的復(fù)雜應(yīng)用,Profiling tool與eclipse緊密地結(jié)合在一起,能在Eclipse環(huán)境下運(yùn)行性能測試。
- 應(yīng)用的性能測試:要在短暫的開發(fā)周期里提交一個(gè)產(chǎn)品是當(dāng)今的流行趨勢,開發(fā)人員(不得不)將更多的精力關(guān)注在應(yīng)用執(zhí)行的功能方面,大多是通過測試、調(diào)試來穩(wěn)固代碼;然而,許多缺陷除非經(jīng)過每天24小時(shí),每周7天的連續(xù)運(yùn)行是不容易暴露的。這類缺陷是不能通過調(diào)試程序的方式來發(fā)現(xiàn)。在發(fā)布一個(gè)產(chǎn)品之前,通過性能分析工具去分析應(yīng)用的執(zhí)行和驗(yàn)證性能問題是很重要的,例如:瓶頸、對象泄漏、系統(tǒng)資源局限。本文介紹了TPTP性能測試工具,示范了如何利用TPTP性能測試工具去定位出一個(gè)java應(yīng)用性能缺陷潛在點(diǎn),以及修復(fù)、驗(yàn)證結(jié)果。
- TPTP 測試工具(翻譯略)
- 利用TPTP對Java程序進(jìn)行性能測試 :本文舉了一個(gè)簡單的關(guān)于product 分類的java應(yīng)用例子,product的信息存儲在分散的一些xml文件當(dāng)中,這個(gè)應(yīng)用將解析這些xml文件,然后把結(jié)果輸出到控制臺,這些xml文件的路徑可以通過程序變量傳遞main函數(shù)讀取,本例的源代碼及xml文件下載連接:ProductCatalog_example.zip以及products.zip
- 在性能測試視圖中開始應(yīng)用:下載上述的ProductCatalog_example.zip,解壓后導(dǎo)入某個(gè)java項(xiàng)目下,選擇Product類-->右鍵--->Profile As --> Java Application,如下圖:

圖一
通過Profile As-->Java Application菜單打開如下對 話框,如圖二所示。對于這個(gè)例子來說,通過程序參數(shù)來設(shè)置包含產(chǎn)品信息的xml文件的文件夾路徑,從圖二可以看到,設(shè)置程序參數(shù)為x:/myPath/products,其中x:/myPath/products文件夾是你從本文中提供的products.zip 下載解壓到本地的路徑。
下一步是通過設(shè)置性能測試選項(xiàng)作為收集執(zhí)行信息的方法。設(shè)置這些選項(xiàng),可以點(diǎn)擊Launch configuration properties 向?qū)е械腗onitor頁,選擇一組適合的性能選項(xiàng)。提示:一組性能測試過濾器是能夠被復(fù)用的。設(shè)置性能測試過濾器的目的是為了在連續(xù)相同的測試中復(fù)用,或者是在需要相同的性能測試信息時(shí)共享這些過濾器。以下的各個(gè)步驟描述了怎樣創(chuàng)建一個(gè)用于剖析Product catalog的應(yīng)用的過濾器。我們將創(chuàng)建一個(gè)叫ProductFilterSet,用于剖析包名前綴為com.sample.product 的包。
- 在Monitor頁中選擇Execution Time Analysis選項(xiàng),如下圖
正如上圖所示,我們選擇的Execution Time Analysis選項(xiàng)能作用于product catalog 程序的連續(xù)運(yùn)行期間,在下一次運(yùn)行該程序的時(shí)候,可以跳過設(shè)置性能測試過濾器的步驟。
2. 選擇編輯選項(xiàng)
2a.選擇Collect boundary classes excluded by the filter set選項(xiàng),設(shè)置Boundary class depth的值為3。通過選擇這個(gè)選項(xiàng),你指明你想收集的信息是:符合過濾條件的方法以及被該方法調(diào)用深度不超過3層的方法。例如:假設(shè)我們設(shè)置的過濾器去收集MyMethod的信息,并且過濾出方法:M1,M2,M3,M4。
如果調(diào)用棧是如下執(zhí)行的:MyMethod>M1>M2>M3>M4,基于在2a中設(shè)置的過濾條件,性能解析器將顯示如下的調(diào)用棧:MyMethod>M1>M2>M3,將不顯示最后一級調(diào)用M3>M4(因?yàn)槌^了3層)。如下圖所示:

3.選擇要剖析的類
在Moniter頁中,選擇Java Profiling項(xiàng),然后雙擊或者單擊編輯按鈕,打開The Filter Set 向?qū)А@肨he Filter Set 界面來選擇你想剖析的類,這里已經(jīng)預(yù)先定義了一組可用的過濾器,就本例來說,你可以通過下面幾步創(chuàng)建一個(gè)新的過濾器:
3a)單擊Add..按鈕,在彈出的對話框中輸入ProductFilterSet,然后單擊OK。
3b)使用Contents of selected filter set列表中的Add按鈕增加兩個(gè)過濾器,如下圖所示:

可以通過在Launch Configuration wizard向?qū)е悬c(diǎn)擊OK按鈕來運(yùn)行Product catalog 程序,在詢問是否切換到Profiling and Logging透視圖時(shí)選擇Yes,你將在Console視圖中看到如下圖所示的結(jié)果:

提示:TPTP性能測試工具允許你和你所剖析的程序之間交互。你能暫停、恢復(fù)監(jiān)聽,運(yùn)行垃圾收集回收對象引用或者中止程序的運(yùn)行。
- 使用Execution Statistics視圖分析性能危險(xiǎn)點(diǎn)
使用Execution Statistics視圖去分析性能危險(xiǎn)點(diǎn),在Profiling Monitor視圖中,右鍵-->Open with > Execution Statistics可以打開Execution Statistics視圖,下圖顯示的是按照方法調(diào)用的累積時(shí)間排序的,累積時(shí)間是指該方法花費(fèi)的所有時(shí)間,包含調(diào)用其他方法的消耗的時(shí)間。
正如上圖所示,Execution Statistics 顯示在最上方的方法:main(java.lang.String[]), readData(java.lang.String) 和createParser() 消耗了最多的執(zhí)行時(shí)間。看見main和readData方法在列表中(的位置)是不奇怪的,因?yàn)榍罢呤浅绦驁?zhí)行的開始點(diǎn),后者從其名字可以看出它從xml文件中讀取產(chǎn)品信息。
使我們覺得奇怪的是方法createParser() ,它僅僅創(chuàng)建了用于解析xml文件的SAX parser 實(shí)例就花費(fèi)了如此高的執(zhí)行時(shí)間。該方法的執(zhí)行時(shí)間占了整個(gè)應(yīng)用的執(zhí)行時(shí)間的42.96%,Execution Statistics 幫助我們分析這個(gè)方法是性能優(yōu)化的潛在的地方。
分析到這里,讓我們看看createParser() 方法的執(zhí)行細(xì)節(jié)。
- 通過方法createParser() 打開Method Invocation Details 視圖
下面我們通過Method Invocation Details 視圖來看看createParser() 調(diào)用慢的原因。在Execution Statistics視圖中雙擊createParser() 方法就可以打開Method Invocation Details 視圖,如下所示:

上圖中顯示了方法createParser()的執(zhí)行信息,就像你看到的一樣,該方法被readData(java.lang.String)調(diào)用了一次,同時(shí)它調(diào)用了5個(gè)不同的方法,在invoked methods 表中,你能看見newSAXParser() 和newInstance() 方法可能就是createParser()方法執(zhí)行慢的原因,這兩個(gè)方法跟createParser()被調(diào)用24次一樣,也被執(zhí)行了24次。
通過分析以上這些數(shù)據(jù),我們發(fā)現(xiàn)改進(jìn)createParser()執(zhí)行時(shí)間的一個(gè)途徑就是改進(jìn)SAXParserFactory的兩個(gè)方法的執(zhí)行,既然我們無法控制這些方法的實(shí)現(xiàn),唯一的途徑就是減少調(diào)用這些方法的次數(shù)。
解決方案是創(chuàng)建一個(gè)parser實(shí)例,并且復(fù)用其去解析所有的xml文件,取代原來每解析一個(gè)文件就創(chuàng)建一個(gè)parser實(shí)例的做法。讓我們打開源代碼并且修復(fù)它。
提示:在進(jìn)行任何之類優(yōu)化之前,要確保被代碼支持。例如,當(dāng)SAXParser不能同時(shí)被多線程使用時(shí),實(shí)例能被復(fù)用;嚴(yán)格來將,實(shí)例在復(fù)用之前應(yīng)該被重置(reset),擁有一套全面的單元測試集來檢驗(yàn)這些修改是個(gè)不錯(cuò)的主意。
可以在Method Invocation Details視圖中右鍵-->Open Source來打開源代碼。源代碼如下圖:

上圖中顯示了createParser()方法的源代碼。注意該方法每次調(diào)用都創(chuàng)建一個(gè)新的SAX parser 。更新代碼,只創(chuàng)建一個(gè)parser實(shí)例,復(fù)用于解析每個(gè)xml文件,如下圖所示:

正如在上圖中描述的,定義了一個(gè)全局的SAXParser 實(shí)例變量parser,createParser()方法初始化parser然后在每次被調(diào)用時(shí)返回該實(shí)例。
讓我們再次執(zhí)行一下Product catalog程序,驗(yàn)證修復(fù)的結(jié)果。
在Java透視圖中選擇Product類,右鍵--->Profile As -->Java Application,程序執(zhí)行完后,打開Execution Statistics 視圖,比較執(zhí)行時(shí)間,下圖所示的是做了性能優(yōu)化后的結(jié)果:

正如你看到的,createParser()方法的執(zhí)行時(shí)間已經(jīng)僅有19%,而在優(yōu)化執(zhí)行卻是將近 43%。注意,隨著xml文件數(shù)量的增加,提升的值將更加明顯,所以,隨著product文件的增加而減少的程序執(zhí)行時(shí)間將是指數(shù)級的。
總結(jié):
本文論述了TPTP性能測試工具能被用于分析和解決性能問題,本文沒有涉及TPTP工具更多的其他使用方面,如果你想了解更多的關(guān)于TPTP工具的能力,有一套的教程和用戶手冊在這里。