Java基准测试工具 —— JMH使用指南

一、基准测试
1.1 什么是基准测试
通过设计合理的测试方法,选用合适的测试工具和被测系统,实现对某个特定目的场景中某项性能指标进行定量的测试。
1.2 基准测试的前置准备
面对日益复杂的系统和不断增长的用户数,以及性能测试可能涉及到的多个业务系统,只有做到基准测试所涉及的业务场景、系统架构、测试环境等在可控状态下,才能得到相对准确的结果,为容量规划、缺陷定位、系统调优提供参考和依据。
测试目的:明确测试的目的,测试什么?用什么测试方法、策略?
测试环境:被测系统的环境是什么,SIT还是UAT或是PAT?
测试限制:要执行测试有哪些限制因素,该如何解决?
风险因素:测试可能存在哪些风险,解决方案是什么?
结果分析:对测试结果如何分析?测试产生的数据如何分析、定位?
1.3 基准测试的意义
为容量规划确定系统和应用程序的极限;
为配置测试的参数和配置选项提供参考依据;
为验收测试确定系统是否具备自己所宣称的能力;
为性能基线的建立提供长期的数据统计来源以及比较基准
需要依赖:

<dependency>
    <groupId>org.openjdk.jmh</groupId>
      <artifactId>jmh-core</artifactId>
    <version>1.23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-generator-annprocess  -->
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.23</version>
</dependency>

例子:

package com.byt.device.service;
 
import com.byt.device.BytDeviceManagerApplication;
import com.byt.device.scheduler.InspectionTaskScheduler;
import org.junit.Test;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
 
import java.util.concurrent.TimeUnit;
 
/**
 * @Author : TT
 * @Date : 2024/2/18
 * @Description: 基准测试
 */
 
@BenchmarkMode(Mode.All)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
public class JMHServiceTest {
 
    private ConfigurableApplicationContext context;
 
    private InspectionTaskScheduler inspectionTaskScheduler;
 
    @Test
    public void test() throws RunnerException {
        Options options = new OptionsBuilder().include(JMHServiceTest.class.getSimpleName()).warmupIterations(2).measurementIterations(2).forks(1).build();
        new Runner(options).run();
    }
 
    @Setup(Level.Trial)
    public void init() {
        context = SpringApplication.run(BytDeviceManagerApplication.class);
 
        inspectionTaskScheduler = context.getBean(InspectionTaskScheduler.class);
    }
 
    @Benchmark
    public void testScheduler() {
        inspectionTaskScheduler.checkTaskTime();
    }
 
}

相关注解解释:

ps:以下注解也可以设置在options 例如:Options options = new OptionsBuilder().include(JMHServiceTest.class.getSimpleName()).warmupIterations(2).measurementIterations(2).forks(1).build(); 中 取其一即可

1.@BenchmarkMode(Mode.All)----可以指定多种测试模式。

Mode.Throughput 计算吞吐量
Mode.AverageTime 计算平均运行时间
Mode.SampleTime 在测试中,随机进行采样执行的时间
Mode.SingleShotTime 测量单次操作的时间
Mode.All 所有模式依次运行

2.@OutputTimeUnit(TimeUnit.SECONDS) —统计结果的时间单元,这个例子TimeUnit.SECONDS,我们在运行后会看到输出结果是统计每秒的吞吐量
3.@Measurement —测试阶段可以指定迭代的次数,每次迭代的运行时间和每次迭代测试调用的数量(通常使用@BenchmarkMode(Mode.SingleShotTime)测试一组操作的开销——而不使用循环)。

测量迭代次数 @Measurement.iteration
每次测量迭代的时长 @Measurement.time
每次测量迭代的时长单位 @Measurement.timeUnit
每次操作基准方法的调用数 @Measurement.batchSize

4.@Warmup–与@Measurement相同,但是用于预热阶段
5.@State—注解定义了给定类实例的可用范围

Scope.Thread 默认状态。每个测试线程分配一个实例;
Scope.Benchmark 所有测试线程共享一个实例,用于测试有状态实例在多线程共享下的性能;
Scope.Group 每个线程组共享一个实例

6.@Setup/@TearDown注解使用Level参数来指定何时调用fixture(@Setup会比Benchmark先执行 用于初始化,@TearDown-用于回收资源)

Level.Trial 默认level。全部benchmark运行(一组迭代)之前/之后 推荐的方式
Level.Iteration 一次迭代之前/之后(一组调用)
Level.Invocation 每个方法调用之前/之后(不推荐使用,除非你清楚这样做的目的)

7.@Fork — 代表启动多个单独的进程分别测试每个方法
8.@Iteration–测试的最小单位
9.@Benchmark — 需要测试的方法

控制台输出结果解释:

#Warmup: 1 iterations, 10 s each — 预热1次 每10秒预热一次
#Measurement: 3 iterations, 10 s each //运行三次 每次运行10秒
#Timeout: 10 min per iteration //
#Threads: 1 thread, will synchronize iterations // 一个线程
#Benchmark mode: Throughput, ops/time //统计性能数据维度是 Throughput 吞吐量
#Benchmark: com.byt.device.service.JMHServiceTest.testScheduler

#Run progress: 0.00% complete, ETA 00:02:00 //
#Fork: 1 of 1 // 一个进程

Result “com.byt.device.service.JMHServiceTest.testScheduler”:
1446251.771 ±(99.9%) 267885.360 us/op [Average]
(min, avg, max) = (1435241.086, 1446251.771, 1462923.343), stdev = 14683.701
CI (99.9%): [1178366.412, 1714137.131] (assumes normal distribution)

标准差(stdev)反映了数值相对于平均值得离散程度,置信区间是指由样本统计量所构造的总体参数的估计区间。在统计学中,一个概率样本的置信区间(Confidence interval)是对这个样本的某个总体参数的区间估计

Benchmark Mode Cnt Score Error Units
JMHServiceTest.baseline avgt 3 ≈ 10⁻⁹ s/op
JMHServiceTest.measureRight avgt 3 ≈ 10⁻⁸ s/op
JMHServiceTest.measureWrong_1 avgt 3 ≈ 10⁻⁸ s/op
JMHServiceTest.measureWrong_2 avgt 3 ≈ 10⁻⁹ s/op
JMHServiceTest.testScheduler12 avgt 3 1.379 ± 0.457 s/op

  • 51
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值