SpringBoot 如何使用 JMH 进行性能测试

本文涉及的产品
性能测试 PTS,5000VUM额度
简介: SpringBoot 如何使用 JMH 进行性能测试

SpringBoot 如何使用 JMH 进行性能测试


在 SpringBoot 应用程序中,我们可以使用 JMH(Java Microbenchmark Harness)进行性能测试。JMH 是一个专门用于微基准测试的工具,可以让我们测试代码在不同条件下的性能表现。使用 JMH 可以让我们更加准确地测试代码的性能,从而优化代码,提高系统的性能。


在本文中,我们将介绍如何使用 JMH 进行性能测试,并编写一个示例测试用例来测试代码的性能。


7df78b94ab1c50bc963e372ddd61abed_561373abe4c24e37a1143f7fa3d78fcc.png


什么是 JMH


JMH 是一个专门用于微基准测试的工具,可以让我们测试代码在不同条件下的性能表现。JMH 是由 OpenJDK 团队开发的,是 Java 语言中最常用的性能测试工具之一。


JMH 可以测量代码的执行时间、方法吞吐量、内存分配、锁消耗等指标。JMH 可以让我们更加准确地测试代码的性能,从而优化代码,提高系统的性能。


JMH 提供了多种测试模式,包括基准测试模式、迭代测试模式、黑盒测试模式等。JMH 还提供了多种测试选项,包括测试线程数、测试次数、测试时间等。


使用 JMH 进行性能测试


在 SpringBoot 中,我们可以使用 JMH 进行性能测试。JMH 可以通过以下步骤进行设置:


1.导入依赖

在 pom.xml 文件中添加以下依赖:


<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.33</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.33</version>
    <scope>test</scope>
</dependency>

2.编写测试类

创建一个测试类,并添加 @State 和 @Benchmark 注解。@State 注解用于指定测试状态,@Benchmark 注解用于指定测试方法。


在测试类中,我们需要定义测试状态,以便在测试中使用。我们可以使用 @State 注解定义测试状态。


@State(Scope.Thread)
public class MyBenchmark {
    private List<String> list;
    @Setup
    public void setup() {
        list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(UUID.randomUUID().toString());
        }
    }
    @TearDown
    public void tearDown() {
        list = null;
    }
    @Benchmark
    public void testSort() {
        Collections.sort(list);
    }
}

在上面的示例中,我们使用 @State(Scope.Thread) 注解定义了一个测试状态。我们在 @Setup 方法中初始化一个包含 10000 个随机字符串的列表,然后在 @TearDown 方法中清空列表。在 @Benchmark 方法中,我们使用 Collections.sort() 方法对列表进行排序。


3.运行测试

在测试方法中,我们使用 JMH 进行性能测试。我们可以使用以下代码运行性能测试:


public class MyBenchmarkTest {
    @Test
    public void testMyBenchmark() throws Exception {
        Options options = new OptionsBuilder()
            .include(MyBenchmark.class.getSimpleName())
            .forks(1)
            .threads(1)
            .warmupIterations(5)
            .measurementIterations(5)
            .mode(Mode.AverageTime)
            .build();
        new Runner(options).run();
    }
}

在上面的示例中,我们使用 OptionsBuilder() 构造函数创建测试选项,并使用 Runner 对象运行性能测试。我们使用 include() 方法指定要测试的类,使用 forks() 方法指定测试进程数,使用 threads() 方法指定测试线程数,使用 warmupIterations() 方法指定预热次数,使用 measurementIterations() 方法指定测试次数,使用 mode()方法指定测试模式。


在示例中,我们使用 Mode.AverageTime 模式进行测试。这种模式会运行多次测试,然后计算测试结果的平均值。Mode.SampleTime 模式会随机选择一些测试用例进行测试,然后计算测试结果的样本平均值。Mode.Throughput 模式会测试代码的吞吐量,即在单位时间内执行的操作数。


4.查看测试结果

在运行测试后,我们可以查看测试结果。JMH 会输出多种测试结果,包括测试时间、吞吐量、内存分配等指标。


在我们的示例中,JMH 输出的测试结果如下所示:


Benchmark             Mode  Cnt   Score   Error  Units
MyBenchmark.testSort  avgt    5  4.517 ± 0.329  us/op


在输出结果中,Benchmark 列显示了测试方法的名称,Mode 列显示了测试模式,Cnt 列显示了测试次数,Score 列显示了测试结果的平均值,Error 列显示了测试结果的误差范围,Units 列显示了测试结果的单位。


在我们的示例中,测试方法的名称为 MyBenchmark.testSort,测试模式为 avgt,测试次数为 5 次,测试结果的平均值为 4.517 微秒,误差范围为 0.329 微秒,单位为每操作微秒。


示例测试用例


下面是一个示例测试用例,用于测试一个简单的字符串拼接方法的性能。


@State(Scope.Thread)
public class StringConcatBenchmark {
    private String str1;
    private String str2;
    @Setup
    public void setup() {
        str1 = "Hello";
        str2 = "World";
    }
    @TearDown
    public void tearDown() {
        str1 = null;
        str2 = null;
    }
    @Benchmark
    public String testStringConcat() {
        return str1 + " " + str2;
    }
}

在上面的示例中,我们使用 @State(Scope.Thread) 注解定义了一个测试状态。在 @Setup 方法中初始化两个字符串,然后在 @TearDown 方法中清空字符串。在 @Benchmark 方法中,我们使用 + 运算符拼接两个字符串。


我们可以使用以下代码运行性能测试:


public class StringConcatBenchmarkTest {
    @Test
    public void testStringConcatBenchmark() throws Exception {
        Options options = new OptionsBuilder()
            .include(StringConcatBenchmark.class.getSimpleName())
            .forks(1)
            .threads(1)
            .warmupIterations(5)
            .measurementIterations(5)
            .mode(Mode.AverageTime)
            .build();
        new Runner(options).run();
    }
}

在运行测试后,JMH 输出的测试结果如下所示:


Benchmark                     Mode  Cnt   Score   Error  Units
StringConcatBenchmark.testStringConcat  avgt    5  3.729 ± 0.142  us/op


在输出结果中,我们可以看到测试方法的名称为 StringConcatBenchmark.testStringConcat,测试模式为 avgt,测试次数为 5 次,测试结果的平均值为 3.729 微秒,误差范围为 0.142 微秒,单位为每操作微秒。


结论


使用 JMH 进行性能测试可以让我们更加准确地测试代码的性能,从而优化代码,提高系统的性能。在 SpringBoot 应用程序中,我们可以使用 JMH 进行性能测试。在进行性能测试时,我们需要导入 JMH 的依赖,编写测试类,并使用 JMH 进行测试。在测试完成后,我们可以查看测试结果,并根据测试结果进行代码优化。


相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
相关文章
|
25天前
|
Java 测试技术 开发者
必学!Spring Boot 单元测试、Mock 与 TestContainer 的高效使用技巧
【10月更文挑战第18天】 在现代软件开发中,单元测试是保证代码质量的重要手段。Spring Boot提供了强大的测试支持,使得编写和运行测试变得更加简单和高效。本文将深入探讨Spring Boot的单元测试、Mock技术以及TestContainer的高效使用技巧,帮助开发者提升测试效率和代码质量。
136 2
|
1月前
|
XML Java 测试技术
【SpringBoot系列】初识Springboot并搭建测试环境
【SpringBoot系列】初识Springboot并搭建测试环境
73 0
|
1月前
|
安全 Java 数据库
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
这篇文章是关于Apache Shiro权限管理框架的详细学习指南,涵盖了Shiro的基本概念、认证与授权流程,并通过Spring Boot测试模块演示了Shiro在单应用环境下的使用,包括与IniRealm、JdbcRealm的集成以及自定义Realm的实现。
43 3
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
|
1月前
|
监控 Java Maven
springboot学习二:springboot 初创建 web 项目、修改banner、热部署插件、切换运行环境、springboot参数配置,打包项目并测试成功
这篇文章介绍了如何快速创建Spring Boot项目,包括项目的初始化、结构、打包部署、修改启动Banner、热部署、环境切换和参数配置等基础操作。
125 0
|
2月前
|
JavaScript 前端开发 Java
Spring Boot+cucumber+契约测试
Spring Boot+cucumber+契约测试
22 0
Spring Boot+cucumber+契约测试
|
3月前
|
Java 测试技术
SpringBoot单元测试快速写法问题之区分链路环节是否应该被Mock如何解决
SpringBoot单元测试快速写法问题之区分链路环节是否应该被Mock如何解决
|
3月前
|
SQL Java 测试技术
SpringBoot单元测试快速写法问题之PorkService 接口中的 getPork 方法的作用如何解决
SpringBoot单元测试快速写法问题之PorkService 接口中的 getPork 方法的作用如何解决
|
3月前
|
Java 测试技术 数据库
SpringBoot单元测试快速写法问题之不想在PandoraBoot工程中Mock Dao层如何解决
SpringBoot单元测试快速写法问题之不想在PandoraBoot工程中Mock Dao层如何解决
|
3月前
|
Java 测试技术 API
SpringBoot单元测试快速写法问题之创建 PorkInst 实例如何解决
SpringBoot单元测试快速写法问题之创建 PorkInst 实例如何解决
|
3月前
|
Java 测试技术 API
SpringBoot单元测试快速写法问题之确定链路上的Mock点如何解决
SpringBoot单元测试快速写法问题之确定链路上的Mock点如何解决