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

前言

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

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

  • 將原本只會執行一次的單元測試用例連續執行 n 次,這個 n 的取值範圍通常是 2000~5000;
  • 統計執行 n 次的平均時間。如果這個平均時間比較長(也就是單次函數調用時間比較長)的話,比如已經達到了秒級,那麼通常情況下這個被測函數的實現邏輯一定需要優化。

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

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

ContiPerf 簡介

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

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

ContiPerf 使用

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

首先,加入 pom 依賴包:

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!--引入 ContiPerf 測試工具-->
        <dependency>
            <groupId>org.databene</groupId>
            <artifactId>contiperf</artifactId>
            <version>2.3.4</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency><dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>

這裏爲了演示,編寫了一個簡單的測試接口:
UnitTestService.java

/**
 * 測試接口類
 * @author zuozewei
 *
 */
public interface UnitTestService {
	
	public String process(String msg);

}

實現類:UnitTestServiceImpl.java

@Service
public class UnitTestServiceImpl implements UnitTestService {

	/**
	 * 爲了測試,這裏直接返回傳入的值
	 */
	@Override
	public String process(String msg) {
		// TODO Auto-generated method stub
		return msg;
	}
}

編寫 UnitTestServiceTest 測試類,進入 ContiPerfRule。

/**
 * 編寫接口性能測試類
 * @author zuozewei
 *
 */
@RunWith(SpringRunner.class)
@SpringBootTest //SpringBootTest 是springboot 用於測試的註解,可指定啓動類或者測試環境等,這裏直接默認。
public class UnitTestServiceTest {
	
	@Autowired
	UnitTestService testService;
	
	// 引入 ContiPerf 進行性能測試
	@Rule
	public ContiPerfRule contiPerfRule = new ContiPerfRule();

	@Test
	@PerfTest(invocations = 10000,threads = 100) //100個線程 執行10000次
	public void test() {
		String msg = "this is a test";
		String result = testService.process(msg);
		//斷言 是否和預期一致
		Assert.assertEquals(msg,result);
	}
}

注意:
@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。

運行測試,控制檯會生成結果:

com.zuozewei.springbootcontiperfdemo.service.UnitTestServiceTest.test
samples: 10000
max:     331
average: 33.3522
median:  30

同時訪問:target/contiperf-report/index.html,會生成圖表:
在這裏插入圖片描述

注意:圖表需要科學上網才能顯示

圖表中的指標:

  • Execution time: 執行時間
  • Throughput: TPS
  • Min. latency: 最小響應時間
  • Average latency: 平均響應時間
  • Median: 響應時間中位數
  • 90%: 90%響應時間範圍
  • Max latency: 最大響應時間

小結

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

示例代碼:
https://github.com/zuozewei/PerformanceTest-Examples/tree/master/contiperf/springboot-contiperf-demo

參考資料:
[1]:https://sourceforge.net/p/contiperf/wiki/Home
[2]:軟件測試52講 茹炳晟

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章