• 基于JMH做Benchmark基准测试


    目录

    BenchMark介绍

    开始前的步骤

    举例代码

    报告分析

    Benchmark注解介绍

    @BenchmarkMode

    @OutputTimeUnit

    @Iteration

    @WarmUp

    @State

    @Fork

    @Meansurement

    @Setup

    @TearDown

    @Benchmark

    @Param


    BenchMark介绍

    BenchMark 又叫做基准测试,主要用来测试一些方法的性能,可以根据不同的参数以不同的单位进行计算(例如可以使用吞吐量为单位,也可以使用平均时间作为单位,在 BenchmarkMode 里面进行调整)。

    开始前的步骤

    项目使用的是 Maven,因此只要对 pom.xml 添加依赖即可。

    1. <dependency>
    2. <groupId>org.openjdk.jmhgroupId>
    3. <artifactId>jmh-coreartifactId>
    4. <version>1.19version>
    5. dependency>
    6. <dependency>
    7. <groupId>org.openjdk.jmhgroupId>
    8. <artifactId>jmh-generator-annprocessartifactId>
    9. <version>1.19version>
    10. <scope>providedscope>
    11. dependency>

    举例代码

    学习多线程锁的时候,在锁清除用到基准测试来测synchronized锁是否会被清除掉。接下来就来看一下 具体的操作步骤以及执行结果吧!!!!

    1. package com.example.testdemo;
    2. import org.openjdk.jmh.annotations.*;
    3. import org.openjdk.jmh.runner.Runner;
    4. import org.openjdk.jmh.runner.RunnerException;
    5. import org.openjdk.jmh.runner.options.Options;
    6. import org.openjdk.jmh.runner.options.OptionsBuilder;
    7. import java.util.concurrent.TimeUnit;
    8. @Fork(1) // Fork进行的数目
    9. @BenchmarkMode(Mode.Throughput) // 调用的平均时间
    10. @Warmup(iterations = 3) // 先预热3轮
    11. @Measurement(iterations = 5) // 进行5轮测试
    12. @OutputTimeUnit(TimeUnit.NANOSECONDS) // 结果所使用的时间单位,纳秒
    13. public class TestEliminateLock {
    14. static int i = 0;
    15. @Benchmark
    16. public void a() throws Exception{
    17. i++;
    18. }
    19. @Benchmark
    20. public void b() throws Exception{
    21. Object o = new Object();
    22. synchronized (o){
    23. i++;
    24. }
    25. }
    26. public static void main(String[] args) throws RunnerException {
    27. Options options = new OptionsBuilder().include(TestEliminateLock.class.getSimpleName()).build();
    28. new Runner(options).run();
    29. }
    30. }

    报告分析

    Benchmark注解介绍

    @BenchmarkMode

            Mode表示JMH进行Benchmark时所使用的模式。通常是测量的纬度不同,或是测量的方式不同。目前JMH共有四种模式:

    1.  Throughput:整体吞吐量,例如“1秒内可以执行多少次调用”,单位是操作数/时间。
    2. AverageTime:调用的平均时间,例如“每次调用平均耗时xxx毫秒”,单位是时间/操作数。
    3. SampleTime:随机取样,最后输出取样结果的分布,例如“99%的调用在xxx毫秒以内,99.99%的调用在xxx毫秒以内”
    4. SingleShotTime: 以上模式都是默认一次 iteration 是 1s,唯有 SingleShotTime 是只运行一次。往往同时把 warmup 次数设为0,用于测试冷启动时的性能。

    @OutputTimeUnit

    输出的时间单位。

    @Iteration

    Iteration 是 JMH 进行测试的最小单位。在大部分模式下,一次 iteration 代表的是一秒,JMH 会在这一秒内不断调用需要 Benchmark 的方法,然后根据模式对其采样,计算吞吐量,计算平均执行时间等。

    @WarmUp

    Warmup 是指在实际进行 Benchmark 前先进行预热的行为。

    为什么需要预热?因为 JVM 的 JIT 机制的存在,如果某个函数被调用多次之后,JVM 会尝试将其编译成为机器码从而提高执行速度。为了让 Benchmark 的结果更加接近真实情况就需要进行预热。

    @State

    类注解,JMH测试类必须使用 @State 注解,它定义了一个类实例的生命周期,可以类比 Spring Bean 的 Scope。由于 JMH 允许多线程同时执行测试,不同的选项含义如下:

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

    @Fork

    进行 fork 的次数。如果 fork 数是2的话,则 JMH 会 fork 出两个进程来进行测试。

    @Meansurement

    提供真正的测试阶段参数。指定迭代的次数,每次迭代的运行时间和每次迭代测试调用的数量(通常使用 @BenchmarkMode(Mode.SingleShotTime) 测试一组操作的开销——而不使用循环)

    @Setup

    方法注解,会在执行 benchmark 之前被执行,正如其名,主要用于初始化。

    @TearDown

    方法注解,与@Setup 相对的,会在所有 benchmark 执行结束以后执行,主要用于资源的回收等。

    @Setup/@TearDown注解使用Level参数来指定何时调用fixture:

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

    @Benchmark

    方法注解,表示该方法是需要进行 benchmark 的对象。

    @Param

    成员注解,可以用来指定某项参数的多种情况。特别适合用来测试一个函数在不同的参数输入的情况下的性能。@Param 注解接收一个String数组,在 @Setup 方法执行前转化为为对应的数据类型。多个 @Param 注解的成员之间是乘积关系,譬如有两个用 @Param 注解的字段,第一个有5个值,第二个字段有2个值,那么每个测试方法会跑5*2=10次。

    期待大家的三连击,你们的支持是我的动力。加油,猿友们!!

  • 相关阅读:
    第二届上汽零束SOA平台开发者大会揭幕,智能汽车生态加速落地
    【ES】笔记-Set集合实践
    深度学习基础之《TensorFlow框架(15)—神经网络》
    UVa1311/LA2666 Servers
    Pytorch 入门
    @PostConstruct虽好,请勿乱用
    《web课程设计》用HTML CSS做一个简洁、漂亮的个人博客网站
    Spring Cloud Gateway 搭建网关
    java计算机毕业设计Web企业客户管理系统源码+mysql数据库+系统+lw文档+部署
    【ROS入门】使用 ROS 动作(Action)机制实现目标请求、进度与完成结果的反馈
  • 原文地址:https://blog.csdn.net/weixin_43552143/article/details/126285790