103.【Java Microbenchmark Harness】(一)

简介: 103.【Java Microbenchmark Harness】

(一)、JMH概述

1.什么是JMH?

JMH(Java Microbenchmark Harness)是一个 Java 工具,用于构建、运行和分析用 Java 和其他针对 JVM 的语言编写的 纳米/微米/毫/宏观 基准测试,而且是由Java虚拟机团队开发的。简单说,就是用来测量代码运行性能,简称 :“Java性能检测工具”。

JMH官网:https://openjdk.org/projects/code-tools/jmh/

JMH源码下载:https://github.com/openjdk/jmh

2.JMH入门操作

(1).没有JMH的时候我们怎么进行测试的?

我们利用结束的时间戳 - 结束后的时间戳

@Test
    void contextLoads() {
        long l1 = System.currentTimeMillis();
        int n=0;
        for (int i = 1; i <100000 ; i++) {
            n+=1;
        }
        System.out.println(n);
        long l2 = System.currentTimeMillis();
        System.out.println("一共消耗时间: "+(l2-l1));
    }
(2).利用JMH进行测试

添加依赖

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

(二)、JMH运用展示

1.Hello JMH

源码

package org.openjdk.jmh.samples;
import org.openjdk.jmh.annotations.Benchmark;
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;
public class JMHSample_01_HelloWorld {
    @Benchmark   //代表我们现在执行测试的就是这个空方法
    public void wellHelloThere() {    //
        // this method was intentionally left blank.
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_01_HelloWorld.class.getSimpleName())  //执行测试方法的载体类是什么。
                .forks(1)  //总共测试几轮,默认我们呢选择1
                .build();
        new Runner(opt).run();  //执行
    }
}

解释

(三)、JMH注解

1.@Warmip和@Measurement (预热和真实执行)【类】

@Warmip 预热

预热: 执行一次,一次1秒

@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间

真实测试执行一次,一次一秒

@Measurement(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间

源码

package org.openjdk.jmh.samples;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Warmup;
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 java.util.concurrent.TimeUnit;
@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间
@Measurement(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间
public class JMHSample_01_HelloWorld {
    @Benchmark   //代表我们现在执行测试的就是这个空方法
    public void wellHelloThere() {    //
        // this method was intentionally left blank.
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_01_HelloWorld.class.getSimpleName())
                .forks(1)
                .build();
        new Runner(opt).run();
    }
}

2.@BenchmarkMode和@OutputTimeUnit (输出方式和输出单位)【方法】

源码

@BenchmarkMode(Mode.Throughput)  //吞吐量测试, 输出报告: 每单位时间会执行多少次
@OutputTimeUnit(TimeUnit.SECONDS) //输出报告的时间单位
package org.openjdk.jmh.samples;
import org.openjdk.jmh.annotations.*;
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 java.util.concurrent.TimeUnit;
@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间
@Measurement(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间
public class JMHSample_02_BenchmarkModes {
    @Benchmark   //执行测试的方法
    @BenchmarkMode(Mode.Throughput)  //吞吐量测试, 输出报告: 每单位时间会执行多少次
    @OutputTimeUnit(TimeUnit.SECONDS) //输出报告的时间单位
    public void measureThroughput() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }
    @Benchmark
    @BenchmarkMode(Mode.AverageTime)  //平均耗时测试, 输出报告每次操作耗时
    @OutputTimeUnit(TimeUnit.SECONDS)  //耗时的单位
    public void measureAvgTime() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }
    @Benchmark
    @BenchmarkMode(Mode.SampleTime)  //抽样测试,输出报告: 会在执行过程中采样(每次操作耗时)
    @OutputTimeUnit(TimeUnit.SECONDS)
    public void measureSamples() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }
    @Benchmark
    @BenchmarkMode(Mode.SingleShotTime)  //冷启动测试,设置这个,此方法在一轮中只运行一次,这个模式主要是为了测试冷启动的性能
    @OutputTimeUnit(TimeUnit.SECONDS)  //输出单位
    public void measureSingleShot() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }
    @Benchmark
    @BenchmarkMode({Mode.Throughput, Mode.AverageTime, Mode.SampleTime, Mode.SingleShotTime})  // 前四种都进行测试。四种模式都会测试一次,输出四种报告
    @OutputTimeUnit(TimeUnit.SECONDS)
    public void measureMultiple() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }
    @Benchmark
    @BenchmarkMode(Mode.All)  // 不可以像第五种一样指定多种测试方法。只能测试全部四种
    @OutputTimeUnit(TimeUnit.SECONDS)
    public void measureAll() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(100);
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_02_BenchmarkModes.class.getSimpleName())
                .forks(1)
                .build();
        new Runner(opt).run();
    }
}

第一个测试

第二个测试

第三个测试

第四次测试

第五次测试

第六次测试



相关文章
|
JSON 数据可视化 Java
103.【Java Microbenchmark Harness】(六)
103.【Java Microbenchmark Harness】
58 0
103.【Java Microbenchmark Harness】(六)
|
Java
103.【Java Microbenchmark Harness】(三)
103.【Java Microbenchmark Harness】
49 0
103.【Java Microbenchmark Harness】(三)
|
Java
103.【Java Microbenchmark Harness】(二)
103.【Java Microbenchmark Harness】
68 0
103.【Java Microbenchmark Harness】(二)
|
Java
103.【Java Microbenchmark Harness】(五)
103.【Java Microbenchmark Harness】
122 0
|
Java 编译器 BI
103.【Java Microbenchmark Harness】(四)
103.【Java Microbenchmark Harness】
77 0
|
Java 测试技术
在java中使用JMH(Java Microbenchmark Harness)做性能测试
在java中使用JMH(Java Microbenchmark Harness)做性能测试
|
9天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
19天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
6天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
25 9
|
9天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####