性能工具之代码级性能测试工具ContiPerf
前言
做性能的同学一定遇到过这样的场景:应用级别的性能测试发现一个操作的响应时间很长,然后要花费很多时间去逐级排查,最后却发现罪魁祸首是代码中某个实现低效的底层算法。这种自上而下的逐级排查定位的方法,效率通常都很低,代价也很高。所以,我们就需要在项目早期,对一些关键算法进行代码级别的性能测试,以防止此类在代码层面就可以被发现的性能问题,遗留到最后的系统性能测试阶段才被发现。但是,从实际执行的层面来讲,代码级性能测试并不存在严格意义上的测试工具,通常的做法是:改造现有的单元测试框架。
而最常使用的改造方法是:
- 将原本只会执行一次的单元测试用例连续执行 n 次,这个 n 的取值范围通常是 2000~5000;
- 统计执行 n 次的平均时间。如果这个平均时间比较长(也就是单次函数调用时间比较长)的话,比如已经达到了秒级,那么通常情况下这个被测函数的实现逻辑一定需要优化。
那么有没有现成的这样的测试工具呢?当然也是有的,比如今天我们介绍的主角-- ContiPerf。
ContiPerf 简介
ContiPerf 是一个轻量级的测试工具,基于JUnit 4 开发,可用于效率测试等。可以指定在线程数量和执行次数,通过限制最大时间和平均执行时间来进行性能测试。官网地址:https://sourceforge.net/p/contiperf/wiki/Home
ContiPerf 使用 接下来我们一起来实践一个例子,
首先,加入 pom 依赖包:
-
-
org.springframework.boot
-
spring-boot-starter
-
-
-
-
-
org.databene
-
contiperf
-
2.3.4
-
test
-
-
-
-
org.springframework.boot
-
spring-boot-starter-test
-
test
-
-
-
org.junit.vintage
-
junit-vintage-engine
-
-
- 【性能工具之代码级性能测试工具ContiPerf】
-
-
org.springframework.boot
-
spring-boot-starter-web
-
-
junit
-
junit
-
test
-
-
/**
-
* 测试接口类
-
* @author zuozewei
-
*
-
*/
-
public interface UnitTestService {
-
-
public String process(String msg);
-
-
}
-
@Service
-
public class UnitTestServiceImpl implements UnitTestService {
-
-
/**
-
* 为了测试,这里直接返回传入的值
-
*/
-
@Override
-
public String process(String msg) {
-
// TODO Auto-generated method stub
-
return msg;
-
}
-
}
-
/**
-
* 编写接口性能测试类
-
* @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注解:
@Required注解:
- invocations:执行次数n,与线程数量无关,默认值为1
- threads:线程池数量n,并发执行n个线程
- duration:重复执行时间n,测试至少执行n毫秒
- @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
文章图片
图表中的指标:
- Execution time: 执行时间
- Throughput: TPS
- Min. latency: 最小响应时间
- Average latency: 平均响应时间
- Median: 响应时间中位数
- 90%: 90%响应时间范围
- Max latency: 最大响应时间
推荐阅读
- PMSJ寻平面设计师之现代(Hyundai)
- 太平之莲
- 闲杂“细雨”
- 七年之痒之后
- 深入理解Go之generate
- 由浅入深理解AOP
- 期刊|期刊 | 国内核心期刊之(北大核心)
- 生活随笔|好天气下的意外之喜
- 感恩之旅第75天
- python学习之|python学习之 实现QQ自动发送消息