Cómo ejecutar JMH desde dentro de las pruebas JUnit?


¿Cómo puedo ejecutar JMH benchmarks dentro de mi proyecto existente usando JUnit tests? La documentación oficial recomienda hacer un proyecto separado, usando el plugin Maven shade, y lanzar JMH dentro del método main. Es necesario y por qué se recomienda?

Author: Aleksandr Dubinsky, 2015-05-27

1 answers

He estado ejecutando JMH dentro de mi proyecto Maven existente usando JUnit sin efectos nocivos aparentes. No puedo responder por qué los autores recomiendan hacer las cosas de manera diferente. No he observado una diferencia en los resultados. JMH lanza una JVM separada para ejecutar benchmarks para aislarlos. Esto es lo que hago:

  • Añade las dependencias JMH a tu POM:

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

    Tenga en cuenta que los he colocado en el ámbito test.

    En Eclipse, es posible que necesite configurar la anotación procesador manualmente. NetBeans maneja esto automáticamente.

  • Crea tu clase JUnit y JMH. He elegido combinar ambos en una sola clase, pero eso depende de ti. Tenga en cuenta que OptionsBuilder.include es lo que realmente determina qué puntos de referencia se ejecutarán desde su prueba JUnit!

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.TimeUnit;
    import org.junit.Test;
    import org.openjdk.jmh.annotations.*;
    import org.openjdk.jmh.infra.Blackhole;
    import org.openjdk.jmh.runner.Runner;
    import org.openjdk.jmh.runner.options.*;
    
    
    public class TestBenchmark 
    {
    
          @Test public void 
        launchBenchmark() throws Exception {
    
                Options opt = new OptionsBuilder()
                    // Specify which benchmarks to run. 
                    // You can be more specific if you'd like to run only one benchmark per test.
                    .include(this.getClass().getName() + ".*")
                    // Set the following options as needed
                    .mode (Mode.AverageTime)
                    .timeUnit(TimeUnit.MICROSECONDS)
                    .warmupTime(TimeValue.seconds(1))
                    .warmupIterations(2)
                    .measurementTime(TimeValue.seconds(1))
                    .measurementIterations(2)
                    .threads(2)
                    .forks(1)
                    .shouldFailOnError(true)
                    .shouldDoGC(true)
                    //.jvmArgs("-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining")
                    //.addProfiler(WinPerfAsmProfiler.class)
                    .build();
    
                new Runner(opt).run();
            }
    
        // The JMH samples are the best documentation for how to use it
        // http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/
        @State (Scope.Thread)
        public static class BenchmarkState
        {
            List<Integer> list;
    
              @Setup (Level.Trial) public void
            initialize() {
    
                    Random rand = new Random();
    
                    list = new ArrayList<>();
                    for (int i = 0; i < 1000; i++)
                        list.add (rand.nextInt());
                }
        }
    
          @Benchmark public void 
        benchmark1 (BenchmarkState state, Blackhole bh) {
    
                List<Integer> list = state.list;
    
                for (int i = 0; i < 1000; i++)
                    bh.consume (list.get (i));
            }
    }
    
  • El procesador de anotación de JMH parece no funcionar bien con compile-on-save en NetBeans. Es posible que tenga que hacer un Clean and Build completo cada vez que modifique los puntos de referencia. (Cualquier sugerencia apreciada!)

  • Ejecute su prueba launchBenchmark y vea los resultados!

    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running com.Foo
    # JMH version: 1.21
    # VM version: JDK 1.8.0_172, Java HotSpot(TM) 64-Bit Server VM, 25.172-b11
    # VM invoker: /usr/lib/jvm/java-8-jdk/jre/bin/java
    # VM options: <none>
    # Warmup: 2 iterations, 1 s each
    # Measurement: 2 iterations, 1 s each
    # Timeout: 10 min per iteration
    # Threads: 2 threads, will synchronize iterations
    # Benchmark mode: Average time, time/op
    # Benchmark: com.Foo.benchmark1
    
    # Run progress: 0.00% complete, ETA 00:00:04
    # Fork: 1 of 1
    # Warmup Iteration   1: 4.258 us/op
    # Warmup Iteration   2: 4.359 us/op
    Iteration   1: 4.121 us/op
    Iteration   2: 4.029 us/op
    
    
    Result "benchmark1":
      4.075 us/op
    
    
    # Run complete. Total time: 00:00:06
    
    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                                Mode  Cnt  Score   Error  Units
    Foo.benchmark1                           avgt    2  4.075          us/op
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.013 sec
    
  • Runner.run even devuelve RunResult objetos sobre los que se pueden hacer aserciones, etc.

 50
Author: Aleksandr Dubinsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-15 10:35:53