天天看點

性能工具之代碼級性能測試工具ContiPerf

做性能的同學一定會遇到過這樣場景:應用級别的性能測試發現一個操作的響應時間很長,然後要花費很多時間去逐級排查,最後卻發現罪魁禍首是代碼中某個實作低效的底層算法。這種自上而下的逐級排查定位的方法,效率通常都很低,代價也很高。是以,我們就需要在項目早期,對一些關鍵算法進行代碼級别的性能測試,以防止此類在代碼層面就可以被發現的性能問題,遺留到最後的系統性能測試階段才被發現。但是,從實際執行的層面來講,代碼級性能測試并不存在嚴格意義上的測試工具,通常的做法是:改造現有的單元測試架構。

而最常使用的改造方法是:

将原本隻會執行一次的單元測試用例連續執行 n 次,這個 n 的取值範圍通常是 2000~5000;

統計執行 n 次的平均時間。如果這個平均時間比較長(也就是單次函數調用時間比較長)的話,比如已經達到了秒級,那麼通常情況下這個被測函數的實作邏輯一定需要優化。

這裡之是以采用執行 n 次的方式,是因為函數執行時間往往是毫秒級的,單次執行的誤差會比較大,是以采用多次執行取平均值的做法。

那麼有沒有現成的這樣的測試工具呢?當然也是有的,比如今天我們介紹的主角-- ContiPerf。

ContiPerf 是一個輕量級的測試工具,基于JUnit 4 開發,可用于效率測試等。可以指定線上程數量和執行次數,通過限制最大時間和平均執行時間來進行性能測試。

官網位址:https://sourceforge.net/p/contiperf/wiki/Home

接下來我們一起來實踐一個例子,

首先,加入 pom 依賴包:

這裡為了示範,編寫了一個簡單的測試接口: UnitTestService.java

實作類:UnitTestServiceImpl.java

編寫 UnitTestServiceTest 測試類,進入 ContiPerfRule。

注意:  @Rule 是J unit 提供的一個擴充接口注解,其接口類為:org.junit.rules.MethodRule,注意在 Junit5 中,已經被 TestRule 所替代了。也可以通過對類指定 @PerfTest 和 @Required,表示類中方法的預設設定。 @PerfTest注解: invocations:執行次數n,與線程數量無關,預設值為1 threads:線程池數量n,并發執行n個線程 duration:重複執行時間n,測試至少執行n毫秒 @Required注解: @Required(throughput = 20):要求每秒至少執行20個測試; @Required(average = 50):要求平均執行時間不超過50ms; @Required(median = 45):要求所有執行的50%不超過45ms; @Required(max = 2000):要求沒有測試超過2s; @Required(totalTime = 5000):要求總的執行時間不超過5s; @Required(percentile90 = 3000):要求90%的測試不超過3s; @Required(percentile95 = 5000):要求95%的測試不超過5s; @Required(percentile99 = 10000):要求99%的測試不超過10s; @Required(percentiles = “66:200,96:500”):要求66%的測試不超過200ms,96%的測試不超過500ms。

運作測試,控制台會生成結果:

同時通路:target/contiperf-report/index.html,會生成圖表: 

性能工具之代碼級性能測試工具ContiPerf
圖表中的名額: Execution time: 執行時間 Throughput: TPS Min. latency: 最小響應時間 Average latency: 平均響應時間 Median: 響應時間中位數 90%: 90%響應時間範圍 Max latency: 最大響應時間

這裡主要是對 Junit 和 ContiPerf 的使用簡單的示例,在單元測試階段的時候考慮做這種代碼級性能測試,肯定會提高 ROI(投入産出比)的,而且代價非常小,希望本文對各位同學都能有所啟發

繼續閱讀