精华内容
参与话题
问答
  • 本文章将会概述一下 基准测试的概念 、StopWatch的基本使用、 JMH的基本使用以用户JMH中常用注解概述。

    在这里插入图片描述

    任何新工具的出现,都是为了解决某个具体问题而诞生的,否则就没有存在的必要了

    本文章将会概述一下 基准测试的概念 、StopWatch的基本使用、 JMH的基本使用以用户JMH中常用注解概述。

    本文章首发于微信公众号(biglead) 我的大前端生涯 ,同步刊登各技术论坛。


    1 引言 gitHub ?

    JMH 全称 Java Microbenchmark Harness ,Microbenchmark 可解析为 短语 micro-benchmark 测试,Microbenchmark也可解析为 micro(基本的)benchmark(标准检查程序) 。

    JMH 是由 Java Jvm 虚拟机团队开发 ,在Jvm 对 Java 文件的编译阶段、类的加载阶段、运行阶段者有持续的不同程度的优化,JMH的诞生就是为了让 Java 开发者能够了解到自己所编写的代码运行的情况,以及性能方面的情况。

    1.1 基准测试 ?

    基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。

    1.2 使用 StopWatch 来进行测试时间计算

    一个常见的问题 就是 我们会说 ArrayList 比 LinkedList 性能好点,那么我们总会要想方法去测试一下,如添加 1000 0000 条数据,看谁消耗的时间少, StopWatch 用来记录这个时间差并可生成对比,如下代码清单 1-1 中所示的测试用例中,分别向 ArrayList 、LinkedList 中添加了 1000 0000 条数据,然后通过 StopWatch 来生成时间消耗对比:

    ///代码清单 1-1 
    package com.example.demo;
    
    import org.junit.jupiter.api.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.util.StopWatch;
    
    
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    
    
    @SpringBootTest
    class DemoApplicationTest2 {
    
      private static final Logger LOG = LoggerFactory.getLogger(DemoApplicationTest2.class);
    
      @Test
      void testArrayAndLinkedList() {
    
        List<String> arrayList = new ArrayList<>();
    
        StopWatch stopWatch = new StopWatch();
    
        //开始计时
        stopWatch.start("arrayList 测试");
    
        for (int i = 0; i < 10000000; i++) {
          arrayList.add("测试数据");
        }
        ///停止计时
        stopWatch.stop();
    
        
        //测试 LinkedList
        List<String> linkedList = new LinkedList<>();
        //开始计时
        stopWatch.start("linkedList 测试");
    
        for (int i = 0; i < 10000000; i++) {
          linkedList.add("测试数据");
        }
        ///停止计时
        stopWatch.stop();
        
        
        LOG.info("arrayList 消耗的总时间 " + stopWatch.prettyPrint());
        LOG.info("arrayList 消耗的总时间 " + stopWatch.getTotalTimeMillis());
      }
      
    }
    
    

    然后执行单元测试后生成 如下结果:
    在这里插入图片描述

    很明显 对于add方法来讲,ArrayList 的性能要比 LinkedList 的性能要好点。

    在这里只是一个粗糙的测试方法,因为:

    • 使用到的 StopWatch ,在其内部也会记录方法的开始的纳秒数,这种操作也会消耗一定的CPU时间。
    • JVM 在运行时对 for 循环也有优化,这样就会导致测试时间包涵了一部分JVM性能优化的执行时间
    • 前后运行的 JVM 环境并不完全相同

    所以为了能更严谨的来进行测试, JMH 就出现了。

    2 JMH 基本使用

    2.1 集成

    JMH是 JDK9自带的,如果你是 JDK9 之前的版本也可以通过导入 openjdk

    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-core</artifactId>
        <version>1.19</version>
    </dependency>
    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-generator-annprocess</artifactId>
        <version>1.19</version>
    </dependency>
    
    2.2 使用 JMH 进行测试
    
    ///代码清单 2-1
    import org.openjdk.jmh.annotations.*;
    import org.openjdk.jmh.runner.Runner;
    import org.openjdk.jmh.runner.options.Options;
    import org.openjdk.jmh.runner.options.OptionsBuilder;
    
    
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    //Mode 表示 JMH 进行 Benchmark 时所使用的模式
    //BenchmarkMode的value是一个数组,可以把几种Mode集合在一起执行,还可以设置为Mode.Al
    @BenchmarkMode(Mode.AverageTime)
    
    //benchmark 结果所使用的时间单位
    //使用java.util.concurrent.TimeUnit中的标准时间单位
    // 微秒
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    
    ///JMH测试类必须使用@State注解,
    // State定义了一个类实例的生命周期,
    // 可以类比Spring Bean的Scope
    @State(Scope.Thread)
    public class DemoApplicationTestJMH {
    
    
      public static void main(String[] args) throws Exception {
    
        String name = DemoApplicationTestJMH.class.getName();
    
        Options options = new OptionsBuilder()
            .include(name )
            .forks(1)
            .measurementIterations(3)
            .warmupIterations(3)
            .build();
        new Runner(options).run();
      }
    
    
      @Benchmark
      public void testArrayList() {
    
        List<String> arrayList = new ArrayList<>();
    
        for (int i = 0; i < 10000000; i++) {
          arrayList.add("测试数据");
        }
    
      }
    
      @Benchmark
      public void testLinkedList() {
    
        //测试 LinkedList
        List<String> linkedList = new LinkedList<>();
    
        for (int i = 0; i < 10000000; i++) {
          linkedList.add("测试数据");
        }
    
      }
    
    }
    
    
    

    然后运行main 方法后控制台日志会输出很长的日志信息,在这里是执行了testArrayList 与testLinkedList两个方法的基准测试,每个方法都会对应一段日志信息,小编在这里将testArrayList 方法 日志信息拆分成两段如下:

    第一段包括 JVM 的启动参数配置信息 以及 JMH 的基本配置

    /Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/bin/java "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=65371: ... 省略路径
    IDEA.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath 
    # JMH version: 1.19
    # VM version: JDK 1.8.0_74, VM 25.74-b02
    # VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/bin/java
    # VM options: -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=65371:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8
    # Warmup: 3 iterations, 1 s each
    # Measurement: 3 iterations, 1 s each
    # Timeout: 10 min per iteration
    # Threads: 1 thread, will synchronize iterations
    # Benchmark mode: Average time, time/op
    # Benchmark: com.example.demo.DemoApplicationTestJMH.testArrayList
    
    # Run progress: 0.00% complete, ETA 00:00:12
    # Fork: 1 of 1
    objc[56915]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/bin/java (0x10d1a44c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10d1e94e0). One of the two will be used. Which one is undefined.
    # Warmup Iteration   1: 101153.611 us/op
    # Warmup Iteration   2: 76302.787 us/op
    # Warmup Iteration   3: 54296.903 us/op
    Iteration   1: 57062.920 us/op
    Iteration   2: 65024.286 us/op
    Iteration   3: 56325.284 us/op
    

    分析如下图 在这里插入图片描述

    在这里插入图片描述
    Warmup 可译为 预热的意思,在 JMH 中,Warmup 所做 的事情就是在基准测试代码正式执行测量(度量)前,对其进行预热,如 JVM运行期的编译、JIT 的优化等等
    第二段 就是JMH 对 testArrayList 方法的测试输出信息了

    Result "com.example.demo.DemoApplicationTestJMH.testArrayList":
      59470.830 ±(99.9%) 87999.595 us/op [Average]
      (min, avg, max) = (56325.284, 59470.830, 65024.286), stdev = 4823.555
      CI (99.9%): [≈ 0, 147470.424] (assumes normal distribution)
    

    在这里插入图片描述

    然后 对于 testLinkedList 方法也会有 相同类似的日志信息只不过是输出的数据不一样,当两个方法执行基准测试完成后 最后会有对比信息日志如下:

    Result "com.example.demo.DemoApplicationTestJMH.testLinkedList":
      206870.042 ±(99.9%) 2571061.260 us/op [Average]
      (min, avg, max) = (104680.987, 206870.042, 367640.921), stdev = 140928.543
      CI (99.9%): [≈ 0, 2777931.302] (assumes normal distribution)
    
    
    # Run complete. Total time: 00:00:16
    
    Benchmark                              Mode  Cnt       Score         Error  Units
    DemoApplicationTestJMH.testArrayList   avgt    3   59470.830 ±   87999.595  us/op
    DemoApplicationTestJMH.testLinkedList  avgt    3  206870.042 ± 2571061.260  us/op
    
    2.3 对比

    我期望与 代码清单 1-1 所使用的 StopWatch 计时对比一下时时间 ,StopWatch 中输出的是纳秒,对应的是 TimeUnit.NANOSECONDS ,所以我需要将 @OutputTimeUnit 配置的单位修改,以使用 JMH 度量后的时间单位输出为纳秒

    @OutputTimeUnit(TimeUnit.NANOSECONDS)
    public class DemoApplicationTestJMH { ...}
    
    

    再次运行度量测试 最终日志如下:

    # Run complete. Total time: 00:00:16
    
    Benchmark                              Mode  Cnt          Score           Error  Units
    DemoApplicationTestJMH.testArrayList   avgt    3   57019569.485 ±  88169595.613  ns/op
    DemoApplicationTestJMH.testLinkedList  avgt    3  368470033.556 ± 535285211.800  ns/op
    
    Process finished with exit code 0
    

    代码清单 1-1 所使用的 StopWatch 日志如下:

    ---------------------------------------------
    ns         %     Task name
    ---------------------------------------------
    177413718  044%  arrayList 测试
    227298885  056%  linkedList 测试
    

    3 参数概述

    3.1 @BenchmarkMode

    对应Mode选项,可用于类或者方法上, 需要注意的是,这个注解的value是一个数组,可以把几种Mode集合在一起执行,还可以设置为Mode.All,即全部执行一遍

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

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

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

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

    3.3 @State

    类注解,JMH测试类必须使用@State注解,State定义了一个类实例的生命周期,可以类比Spring Bean的Scope。

    由于JMH允许多线程同时执行测试,不同的选项含义如下:

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

    用来配置benchmark 结果所使用的时间单位,可用于类或者方法注解,使用java.util.concurrent.TimeUnit中的标准时间单位。

    TimeUnit.DAYS          //天  
    TimeUnit.HOURS         //小时  
    TimeUnit.MINUTES       //分钟  
    TimeUnit.SECONDS       //秒  
    TimeUnit.MILLISECONDS  //毫秒 
    TimeUnit.NANOSECONDS   //毫微秒 纳秒
    TimeUnit.MICROSECONDS  //微秒
    
    3.5 其他

    @Benchmark

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

    @Setup

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

    @TearDown

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

    @Param

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

    在这里插入图片描述

    展开全文
  • Java JMH基准教程

    2020-06-04 03:25:37
    Benchmark (N) Mode Cnt Score Error Units BenchmarkLoop.loopFor 10000000 avgt 10 61.673 ± 1.251 ms/op BenchmarkLoop.loopForEach 10000000 avgt 10 67.582 ±...
    Benchmark                        (N)  Mode  Cnt   Score   Error  Units
    BenchmarkLoop.loopFor       10000000  avgt   10  61.673 ± 1.251  ms/op
    BenchmarkLoop.loopForEach   10000000  avgt   10  67.582 ± 1.034  ms/op
    BenchmarkLoop.loopIterator  10000000  avgt   10  66.087 ± 1.534  ms/op
    BenchmarkLoop.loopWhile     10000000  avgt   10  60.660 ± 0.279  ms/op

    在Java中,我们可以使用JMH(Java Microbenchmark Harness)框架来衡量功能的性能。

    经过测试

    • 捷运1.21
    • Java 10
    • Maven的3.6
    • CPU i7-7700

    在本教程中,我们将向您展示如何使用JMH来测量不同的循环方法( for, while, iterator and foreach

    1. JMH

    要使用JHM,我们需要声明jmh-corejmh-generator-annprocess (JMH注释)

    pom.xml
    <properties>
            <jmh.version>1.21</jmh.version>
        </properties>
    
    	<dependencies>
            <dependency>
                <groupId>org.openjdk.jmh</groupId>
                <artifactId>jmh-core</artifactId>
                <version>${jmh.version}</version>
            </dependency>
            <dependency>
                <groupId>org.openjdk.jmh</groupId>
                <artifactId>jmh-generator-annprocess</artifactId>
                <version>${jmh.version}</version>
            </dependency>
        </dependencies>

    2. JMH – Mode.AverageTime

    2.1 JMH Mode.AverageTime示例,用于测量不同循环方法的性能,以循环包含1000万个String的List

    BenchmarkLoop.java
    package com.mkyong.benchmark;
    
    import org.openjdk.jmh.annotations.*;
    import org.openjdk.jmh.infra.Blackhole;
    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.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    @State(Scope.Benchmark)
    @Fork(value = 2, jvmArgs = {"-Xms2G", "-Xmx2G"})
    //@Warmup(iterations = 3)
    //@Measurement(iterations = 8)
    public class BenchmarkLoop {
    
        @Param({"10000000"})
        private int N;
    
        private List<String> DATA_FOR_TESTING;
    
        public static void main(String[] args) throws RunnerException {
    
            Options opt = new OptionsBuilder()
                    .include(BenchmarkLoop.class.getSimpleName())
                    .forks(1)
                    .build();
    
            new Runner(opt).run();
        }
    
        @Setup
        public void setup() {
            DATA_FOR_TESTING = createData();
        }
    
        @Benchmark
        public void loopFor(Blackhole bh) {
            for (int i = 0; i < DATA_FOR_TESTING.size(); i++) {
                String s = DATA_FOR_TESTING.get(i); //take out n consume, fair with foreach
                bh.consume(s);
            }
        }
    
        @Benchmark
        public void loopWhile(Blackhole bh) {
            int i = 0;
            while (i < DATA_FOR_TESTING.size()) {
                String s = DATA_FOR_TESTING.get(i);
                bh.consume(s);
                i++;
            }
        }
    
        @Benchmark
        public void loopForEach(Blackhole bh) {
            for (String s : DATA_FOR_TESTING) {
                bh.consume(s);
            }
        }
    
        @Benchmark
        public void loopIterator(Blackhole bh) {
            Iterator<String> iterator = DATA_FOR_TESTING.iterator();
            while (iterator.hasNext()) {
                String s = iterator.next();
                bh.consume(s);
            }
        }
    
        private List<String> createData() {
            List<String> data = new ArrayList<>();
            for (int i = 0; i < N; i++) {
                data.add("Number : " + i);
            }
            return data;
        }
    
    }

    2.2在上面的代码中,JMH将创建2个派生,每个派生包含5个预热迭代(JVM预热,忽略结果)和5个测量迭代(用于计算),例如:

    # Run progress: 0.00% complete, ETA 00:13:20
    # Fork: 1 of 2
    # Warmup Iteration   1: 60.920 ms/op
    # Warmup Iteration   2: 60.745 ms/op
    # Warmup Iteration   3: 60.818 ms/op
    # Warmup Iteration   4: 60.659 ms/op
    # Warmup Iteration   5: 60.765 ms/op
    Iteration   1: 63.579 ms/op
    Iteration   2: 61.622 ms/op
    Iteration   3: 61.869 ms/op
    Iteration   4: 61.730 ms/op
    Iteration   5: 62.207 ms/op
    
    # Run progress: 12.50% complete, ETA 00:11:50
    # Fork: 2 of 2
    # Warmup Iteration   1: 60.915 ms/op
    # Warmup Iteration   2: 61.527 ms/op
    # Warmup Iteration   3: 62.329 ms/op
    # Warmup Iteration   4: 62.729 ms/op
    # Warmup Iteration   5: 61.693 ms/op
    Iteration   1: 60.822 ms/op
    Iteration   2: 61.220 ms/op
    Iteration   3: 61.216 ms/op
    Iteration   4: 60.652 ms/op
    Iteration   5: 61.818 ms/op
    
    Result "com.mkyong.benchmark.BenchmarkLoop.loopFor":
      61.673 ±(99.9%) 1.251 ms/op [Average]
      (min, avg, max) = (60.652, 61.673, 63.579), stdev = 0.828
      CI (99.9%): [60.422, 62.925] (assumes normal distribution)

    2.3预热迭代和测量迭代是可配置的:

    @Warmup(iterations = 3) 		// Warmup Iteration = 3
    @Measurement(iterations = 8) 	// Iteration = 8

    2.4我们甚至可以在启动真正的前叉进行测量之前对整个前叉进行加热。

    @Fork(value = 2, jvmArgs = {"-Xms2G", "-Xmx2G"}, warmups = 2)

    3.如何运行JMH –#1 Maven

    有两种方法可以运行JMH基准测试,使用Maven或直接通过JMH Runner类运行它。

    3.1 Maven,将其打包为JAR并通过org.openjdk.jmh.Main类运行。

    pom.xml
    <build>
    	<plugins>
    		<plugin>
    			<groupId>org.apache.maven.plugins</groupId>
    			<artifactId>maven-shade-plugin</artifactId>
    			<version>3.2.0</version>
    			<executions>
    				<execution>
    					<phase>package</phase>
    					<goals>
    						<goal>shade</goal>
    					</goals>
    					<configuration>
    						<finalName>benchmarks</finalName>
    						<transformers>
    							<transformer
    									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
    								<mainClass>org.openjdk.jmh.Main</mainClass>
    							</transformer>
    						</transformers>
    					</configuration>
    				</execution>
    			</executions>
    		</plugin>
    	</plugins>
    </build>

    3.2 mvn package ,它将生成一个benchmarks.jar ,只需正常启动JAR。

    Terminal
    $ mvn package 
    
    $ java -jar target\benchmarks.jar BenchmarkLoop

    4.如何运行JMH –#2 JMH Runner

    您可以直接通过JMH Runner类运行基准测试。

    BenchmarkLoop.java
    package com.mkyong.benchmark;
    
    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.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    @Fork(value = 2, jvmArgs = {"-Xms2G", "-Xmx2G"})
    public class BenchmarkLoop {
    
        private static final int N = 10_000_000;
    
        private static List<String> DATA_FOR_TESTING = createData();
    
        public static void main(String[] args) throws RunnerException {
    
            Options opt = new OptionsBuilder()
                    .include(BenchmarkLoop.class.getSimpleName())
                    .forks(1)
                    .build();
    
            new Runner(opt).run();
        }
    
        // Benchmark code
    
    }

    5.结果

    5.1查看结果,以循环包含1000万个String对象的List ,经典的while loop是最快的循环。 但是,差异并不大。

    Benchmark                        (N)  Mode  Cnt   Score   Error  Units
    BenchmarkLoop.loopFor       10000000  avgt   10  61.673 ± 1.251  ms/op
    BenchmarkLoop.loopForEach   10000000  avgt   10  67.582 ± 1.034  ms/op
    BenchmarkLoop.loopIterator  10000000  avgt   10  66.087 ± 1.534  ms/op
    BenchmarkLoop.loopWhile     10000000  avgt   10  60.660 ± 0.279  ms/op

    5.2详细信息,仅供参考。

    $ java -jar target\benchmarks.jar BenchmarkLoop
    
    # JMH version: 1.21
    # VM version: JDK 10.0.1, Java HotSpot(TM) 64-Bit Server VM, 10.0.1+10
    # VM invoker: C:\Program Files\Java\jre-10.0.1\bin\java.exe
    # VM options: -Xms2G -Xmx2G
    # Warmup: 5 iterations, 10 s each
    # Measurement: 5 iterations, 10 s each
    # Timeout: 10 min per iteration
    # Threads: 1 thread, will synchronize iterations
    # Benchmark mode: Average time, time/op
    # Benchmark: com.mkyong.benchmark.BenchmarkLoop.loopFor
    # Parameters: (N = 10000000)
    
    # Run progress: 0.00% complete, ETA 00:13:20
    # Fork: 1 of 2
    # Warmup Iteration   1: 60.920 ms/op
    # Warmup Iteration   2: 60.745 ms/op
    # Warmup Iteration   3: 60.818 ms/op
    # Warmup Iteration   4: 60.659 ms/op
    # Warmup Iteration   5: 60.765 ms/op
    Iteration   1: 63.579 ms/op
    Iteration   2: 61.622 ms/op
    Iteration   3: 61.869 ms/op
    Iteration   4: 61.730 ms/op
    Iteration   5: 62.207 ms/op
    
    # Run progress: 12.50% complete, ETA 00:11:50
    # Fork: 2 of 2
    # Warmup Iteration   1: 60.915 ms/op
    # Warmup Iteration   2: 61.527 ms/op
    # Warmup Iteration   3: 62.329 ms/op
    # Warmup Iteration   4: 62.729 ms/op
    # Warmup Iteration   5: 61.693 ms/op
    Iteration   1: 60.822 ms/op
    Iteration   2: 61.220 ms/op
    Iteration   3: 61.216 ms/op
    Iteration   4: 60.652 ms/op
    Iteration   5: 61.818 ms/op
    
    
    Result "com.mkyong.benchmark.BenchmarkLoop.loopFor":
      61.673 ±(99.9%) 1.251 ms/op [Average]
      (min, avg, max) = (60.652, 61.673, 63.579), stdev = 0.828
      CI (99.9%): [60.422, 62.925] (assumes normal distribution)
    
    
    # JMH version: 1.21
    # VM version: JDK 10.0.1, Java HotSpot(TM) 64-Bit Server VM, 10.0.1+10
    # VM invoker: C:\Program Files\Java\jre-10.0.1\bin\java.exe
    # VM options: -Xms2G -Xmx2G
    # Warmup: 5 iterations, 10 s each
    # Measurement: 5 iterations, 10 s each
    # Timeout: 10 min per iteration
    # Threads: 1 thread, will synchronize iterations
    # Benchmark mode: Average time, time/op
    # Benchmark: com.mkyong.benchmark.BenchmarkLoop.loopForEach
    # Parameters: (N = 10000000)
    
    # Run progress: 25.00% complete, ETA 00:10:08
    # Fork: 1 of 2
    # Warmup Iteration   1: 67.938 ms/op
    # Warmup Iteration   2: 67.921 ms/op
    # Warmup Iteration   3: 68.064 ms/op
    # Warmup Iteration   4: 68.172 ms/op
    # Warmup Iteration   5: 68.181 ms/op
    Iteration   1: 68.378 ms/op
    Iteration   2: 68.069 ms/op
    Iteration   3: 68.487 ms/op
    Iteration   4: 68.300 ms/op
    Iteration   5: 67.635 ms/op
    
    # Run progress: 37.50% complete, ETA 00:08:27
    # Fork: 2 of 2
    # Warmup Iteration   1: 67.303 ms/op
    # Warmup Iteration   2: 67.062 ms/op
    # Warmup Iteration   3: 66.516 ms/op
    # Warmup Iteration   4: 66.973 ms/op
    # Warmup Iteration   5: 66.843 ms/op
    Iteration   1: 67.157 ms/op
    Iteration   2: 66.763 ms/op
    Iteration   3: 67.237 ms/op
    Iteration   4: 67.116 ms/op
    Iteration   5: 66.679 ms/op
    
    
    Result "com.mkyong.benchmark.BenchmarkLoop.loopForEach":
      67.582 ±(99.9%) 1.034 ms/op [Average]
      (min, avg, max) = (66.679, 67.582, 68.487), stdev = 0.684
      CI (99.9%): [66.548, 68.616] (assumes normal distribution)
    
    
    # JMH version: 1.21
    # VM version: JDK 10.0.1, Java HotSpot(TM) 64-Bit Server VM, 10.0.1+10
    # VM invoker: C:\Program Files\Java\jre-10.0.1\bin\java.exe
    # VM options: -Xms2G -Xmx2G
    # Warmup: 5 iterations, 10 s each
    # Measurement: 5 iterations, 10 s each
    # Timeout: 10 min per iteration
    # Threads: 1 thread, will synchronize iterations
    # Benchmark mode: Average time, time/op
    # Benchmark: com.mkyong.benchmark.BenchmarkLoop.loopIterator
    # Parameters: (N = 10000000)
    
    # Run progress: 50.00% complete, ETA 00:06:46
    # Fork: 1 of 2
    # Warmup Iteration   1: 67.336 ms/op
    # Warmup Iteration   2: 73.008 ms/op
    # Warmup Iteration   3: 66.646 ms/op
    # Warmup Iteration   4: 70.157 ms/op
    # Warmup Iteration   5: 68.373 ms/op
    Iteration   1: 66.385 ms/op
    Iteration   2: 66.309 ms/op
    Iteration   3: 66.474 ms/op
    Iteration   4: 68.529 ms/op
    Iteration   5: 66.447 ms/op
    
    # Run progress: 62.50% complete, ETA 00:05:04
    # Fork: 2 of 2
    # Warmup Iteration   1: 65.499 ms/op
    # Warmup Iteration   2: 65.540 ms/op
    # Warmup Iteration   3: 67.328 ms/op
    # Warmup Iteration   4: 65.926 ms/op
    # Warmup Iteration   5: 65.790 ms/op
    Iteration   1: 65.350 ms/op
    Iteration   2: 65.634 ms/op
    Iteration   3: 65.353 ms/op
    Iteration   4: 65.164 ms/op
    Iteration   5: 65.225 ms/op
    
    
    Result "com.mkyong.benchmark.BenchmarkLoop.loopIterator":
      66.087 ±(99.9%) 1.534 ms/op [Average]
      (min, avg, max) = (65.164, 66.087, 68.529), stdev = 1.015
      CI (99.9%): [64.553, 67.621] (assumes normal distribution)
    
    
    # JMH version: 1.21
    # VM version: JDK 10.0.1, Java HotSpot(TM) 64-Bit Server VM, 10.0.1+10
    # VM invoker: C:\Program Files\Java\jre-10.0.1\bin\java.exe
    # VM options: -Xms2G -Xmx2G
    # Warmup: 5 iterations, 10 s each
    # Measurement: 5 iterations, 10 s each
    # Timeout: 10 min per iteration
    # Threads: 1 thread, will synchronize iterations
    # Benchmark mode: Average time, time/op
    # Benchmark: com.mkyong.benchmark.BenchmarkLoop.loopWhile
    # Parameters: (N = 10000000)
    
    # Run progress: 75.00% complete, ETA 00:03:22
    # Fork: 1 of 2
    # Warmup Iteration   1: 60.290 ms/op
    # Warmup Iteration   2: 60.161 ms/op
    # Warmup Iteration   3: 60.245 ms/op
    # Warmup Iteration   4: 60.613 ms/op
    # Warmup Iteration   5: 60.697 ms/op
    Iteration   1: 60.842 ms/op
    Iteration   2: 61.062 ms/op
    Iteration   3: 60.417 ms/op
    Iteration   4: 60.650 ms/op
    Iteration   5: 60.514 ms/op
    
    # Run progress: 87.50% complete, ETA 00:01:41
    # Fork: 2 of 2
    # Warmup Iteration   1: 60.845 ms/op
    # Warmup Iteration   2: 60.927 ms/op
    # Warmup Iteration   3: 60.832 ms/op
    # Warmup Iteration   4: 60.817 ms/op
    # Warmup Iteration   5: 61.078 ms/op
    Iteration   1: 60.612 ms/op
    Iteration   2: 60.516 ms/op
    Iteration   3: 60.647 ms/op
    Iteration   4: 60.607 ms/op
    Iteration   5: 60.733 ms/op
    
    
    Result "com.mkyong.benchmark.BenchmarkLoop.loopWhile":
      60.660 ±(99.9%) 0.279 ms/op [Average]
      (min, avg, max) = (60.417, 60.660, 61.062), stdev = 0.184
      CI (99.9%): [60.381, 60.939] (assumes normal distribution)
    
    
    # Run complete. Total time: 00:13:31
    
    REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
    why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
    experiments, perform baseline and negative tests that provide experimental control, make sure
    the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
    Do not assume the numbers tell you what you want them to tell.
    
    Benchmark                        (N)  Mode  Cnt   Score   Error  Units
    BenchmarkLoop.loopFor       10000000  avgt   10  61.673 ± 1.251  ms/op
    BenchmarkLoop.loopForEach   10000000  avgt   10  67.582 ± 1.034  ms/op
    BenchmarkLoop.loopIterator  10000000  avgt   10  66.087 ± 1.534  ms/op
    BenchmarkLoop.loopWhile     10000000  avgt   10  60.660 ± 0.279  ms/op

    注意
    希望本教程为您提供使用JMH基准测试的快速入门指南,有关JMH示例的更多高级信息,请访问此官方JMH示例链接。

    注意
    正向循环与反向循环如何? 哪一个更快? 访问此JMH测试

    下载源代码

    $ git clone https://github.com/mkyong/jmh-benchmark
    $ mvn软件包
    $ java -jar target \ benchmarks.jar BenchmarkLoop

    参考文献

    1. OpenJDK:jmh
    2. JHM示例
    3. Maven –如何创建Java项目
    4. Java – While vs For vs Iterator性能测试

    翻译自: https://mkyong.com/java/java-jmh-benchmark-tutorial/

    展开全文
  • 这篇文章最初出现在Thorben Janssen的Java EE博客上,每周都会发布Java新闻: Thoughts-on-java.org 。 Java Microbenchmarking Harness由OpenJDK团队开发,用于对自己的代码进行基准测试。 但是它不仅被他们使用...

    java jmh

    这篇文章最初出现在Thorben Janssen的Java EE博客上,每周都会发布Java新闻: Thoughts-on-java.org

    Java Microbenchmarking Harness由OpenJDK团队开发,用于对自己的代码进行基准测试。 但是它不仅被他们使用,它已经成为Java世界中最流行的基准测试工具之一。 如果您到目前为止还没有使用过它,那么应该看看Alex Zhitnitsky的动手实践: Java 9 Code Tools:Java Microbenchmarking Harness的动手实践

    Java EE

    Abhishek Gupta写了一篇有趣的文章,介绍了如何使用Java EE实现重试机制。 您只需要一个简单的Interceptor和一个用于提供一些配置数据的附加注释: 在Java EE应用程序中实现自动重试

    使用Hibernate实现持久层很容易。 不幸的是,引入一些效率低下和性能问题也很容易。 为了避免它们,您需要对Hibernate和一些更高级的功能有更深入的了解: 7个提高Hibernate性能的技巧

    迁移大型应用程序通常会花费很多精力,并且存在向代码库添加新错误的风险。 这可能是为什么仍然有那么多Java EE 5应用程序的一些原因。 但是,正如Roberto Cortez在他最近的博客文章中指出的那样,也有充分的理由将这些应用程序迁移到Java EE 7: 将遗留从Java EE 5减少到7

    断路器模式在微服务架构中非常流行。 在配置的呼叫数目失败后,它将停止对特定服务的进一步呼叫。 但是如何实现这种模式? 嗯,显然有多种方法可以做到,其中一种是简单的Java EE拦截器:Java EE的一种简约的断路器模式实现

    Java一

    正如我上周告诉您的那样,Oracle记录了JavaOne会话并将其上传到他们的YouTube频道。 这些视频的唯一问题是录音并未分成不同的话题。 Oracle为每天和每个房间上传一个文件。 因此,您要么花一些时间来查找特定的会话,要么可以查看dzjay的Reddit帖子: JavaOne 2015 Sessions

    它为您提供时间安排并链接到100多个Java One会话。 非常感谢dzjay!

    即将举行的活动

    Martyn Taylor将在11月10日世界标准时间下午6点在Virtual:JBUG上发表有关物联网消息传递的演讲。

    翻译自: https://jaxenter.com/java-weekly-4615-jmh-circuit-breaker-hibernate-tips-122087.html

    java jmh

    展开全文
  • - fix duplicate jmh generated classes (jmh-generated-classes, jmh-generated-sources) - fix broken jmh metadata files (BenchmarkList, CompilerHints) - fix jmh command line jar (inline dependencies with...
  • Java基准测试 JMH

    千次阅读 2017-10-16 17:33:00
    微基准测试 jmh 功能介绍 冗余代码消除

    引入到工程

    <dependencies>
        <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-core</artifactId>
        <version>1.9</version>
        </dependency>
    </dependencies>

    功能支持

    测量方式(@BenchmarkMode)
    • Mode.Throughput [default]计算一个时间单位内操作数量
    • Mode.AverageTime 计算平均运行时间

    时间单位(@OutputTimeUnit)

    • TimeUnit.SECONDS [default]秒
    • TimeUnit.MILLISECONDS 毫秒(10-3秒)
    • TimeUnit.MICROSECONDS 微秒(10-6秒)
    • TimeUnit.NANOSECONDS 纳秒(10-9秒)

    多线程共享(@State)

    • Scope.Thread [default]实例将分配给运行给定测试的每个线程
    • Scope.Benchmark 运行相同测试的所有线程将共享实例,可以用来测试状态对象的多线程性能
    • Scope.Group 实例分配给每个线程组(查看后面的线程组部分)

    fork新的线程(@Fork)

    默认JMH为每个试验(迭代集合)fork一个新的java进程。
    不要把forks设为0,除非你清楚这样做的目的。

    这样可以防止前面收集的“资料”——其他被加载类以及它们执行的信息对当前测试的影响。比如,实现了相同接口的两个类,测试它们的性能,那么第一个实现(目标测试类)可能比第二个快,因为JIT发现第二个实现类后就把第一个实现的直接方法调用替换为接口方法调用。

    测试阶段的参数(@Measurement @Warmup)

    • 可以指定迭代的次数
    • 可以指定每次迭代的运行时间和时间单位(默认为秒)

    Measurement用于测试阶段
    Warmup用于预热阶段(不计入测试时长)

    线程数(@Threads)

    • 默认是Runtime.getRuntime().availableProcessors()

    fixtures注解(@Setup @TearDown)

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

    开始运行

    使用IDEA运行微基准测试(推荐)

    在IDEA中,只需要在Plugins的列表中,搜索一下JMH关键字,就能找到JMH Plugin,然后安装下来,重启一下IDEA,就能运行JMH微测试。

    main函数调用

    main方法中通过几句代码调用JMH库

    Options opt = new OptionsBuilder()
        .include(testClazz.class.getSimpleName())
        .forks(1)
        .build();
    new Runner(opt).run();

    anti-编译器优化

    冗余代码消除是microbenchmark中众所周知的问题。通常的解决方法是以某种方式使用计算结果。JMH本身不会实施对冗余代码的消除。

    方法一:方法返回值

        @Benchmark
        public int testMethod() {
            int a = 1;
            int b = 2;
            int sum = a + b;
    
            return sum;
        }

    方法二:交给Blackhole

       @Benchmark
       public void testMethod(Blackhole blackhole) {
            int a = 1;
            int b = 2;
            int sum = a + b;
            blackhole.consume(sum);
        }

    参考:JMH简介
    参考:JMH - Java Microbenchmark Harness

    展开全文
  • 作者:kiritomoe 来源:Kirito的技术分享前言JMH (http://openjdk.java.net/projects/code-tools/jmh/) ...
  • 本文详细介绍了JMH的概念以及如何使用HMH进行Java的方法的性能测试!
  • JMHJava Microbenchmark Harness 的缩写。中文意思大致是 “JAVA 微基准测试套件”。首先先明白什么是“基准测试”。百度百科给的定义如下: 基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对...
  • JMH是新的microbenchmark(微基准测试)框架(2013年首次发布)。与其他众多框架相比它的特色优势在于,它是由Oracle实现JIT的相同人员开发的。特别是我想提一下Aleksey Shipilev和他优秀的博客文章。JMH可能与最新...
  • Java 性能测试工具 JMH

    千次阅读 2017-05-23 15:57:32
    最近在看《Java8函数式编程》时,发现了一个性能测试工具 JMH(Java Microbenchmark Harness)。这个工具方便了我们进行微基准测试。比如,在进行微基准测试时,我们想要测试的是“程序被JVM编译成机器代码(而不是...
  • java中使用JMHJava Microbenchmark Harness)做性能测试 JMH的全称是Java Microbenchmark Harness,是一个open JDK中用来做性能测试的套件。该套件已经被包含在了JDK 12中。 本文将会讲解如何使用JMH来在java中...
  • JMH-Java性能测试

    2020-10-24 16:07:55
    Mode 表示 JMH 进行 Benchmark 时所使用的模式。通常是测量的维度不同,或是测量的方式不同。 目前JMH 共有四种模式: Throughput: 整体吞吐量,例如“1秒内可以执行多少次调用”。 AverageTime: 调用的平均时间,...
  • JAVA高并发之JMH使用

    2020-10-15 16:42:21
    package JMHExp01; 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 java.ut

空空如也

1 2 3 4 5 ... 20
收藏数 506
精华内容 202
热门标签
关键字:

java jmh

java 订阅