java - tutorial - pruebas unitarias
¿Cómo ejecutar JMH desde dentro de las pruebas de JUnit? (1)
¿Cómo puedo ejecutar los puntos de referencia de JMH dentro de mi proyecto existente usando las pruebas JUnit? La documentación oficial recomienda realizar un proyecto por separado, usar el complemento de sombra de Maven y lanzar JMH dentro del método main
. ¿Es esto necesario y por qué se recomienda?
He estado ejecutando JMH dentro de mi proyecto Maven existente usando JUnit sin efectos 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 puntos de referencia para aislarlos. Esto es lo que hago:
Agregue las dependencias de JMH a su 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 puesto en la
test
alcance.En Eclipse, es posible que deba configurar el procesador de anotaciones 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 anotaciones de JMH parece no funcionar bien con compilar para guardar en NetBeans. Es posible que deba realizar una
Clean and Build
cada vez que modifique los puntos de referencia. (Cualquier sugerencia apreciada!)¡Ejecute su prueba de
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
incluso devuelve objetosRunResult
en los que puede realizar aserciones, etc.