Come posso eseguire benchmark JMH all'interno del mio progetto esistente usando i test JUnit? La documentazione ufficiale consiglia di creare un progetto separato, utilizzando il plug-in Maven per il colore e l'avvio di JMH nel metodo main
. È necessario e perché è raccomandato?Come eseguire JMH da test JUnit interni?
risposta
Ho eseguito JMH all'interno del mio progetto Maven esistente utilizzando JUnit senza apparenti effetti negativi. Non posso rispondere perché gli autori raccomandano di fare le cose in modo diverso. Non ho osservato una differenza nei risultati. JMH lancia una JVM separata per eseguire benchmark per isolarli. Ecco quello che faccio:
Aggiungere le dipendenze JMH al POM:
<dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>1.9.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-generator-annprocess</artifactId> <version>1.9.3</version> <scope>test</scope> </dependency>
Si noti che le ho messo in ambito
test
.In Eclipse, potrebbe essere necessario configurare manualmente il processore di annotazione. NetBeans gestisce questo automaticamente.
Crea la tua classe JUnit e JMH. Ho scelto di combinare entrambi in una singola classe, ma dipende da te. Si noti che
OptionsBuilder.include
è ciò che determina effettivamente quali benchmark verranno eseguiti dal test JUnit!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 : LoopUtils.range (1000)) 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)); } }
processore annotazione di JMH sembra non funzionare bene con compilazione on-save in NetBeans. Potrebbe essere necessario eseguire un completo
Clean and Build
ogni volta che si modificano i benchmark. (Qualsiasi suggerimento apprezzato!)Esegui il test
launchBenchmark
e guarda i risultati!------------------------------------------------------- T E S T S ------------------------------------------------------- Running net.almson.util.TestBenchmark # JMH 1.9.3 (released 12 days ago) # VM invoker: C:\Program Files\Java\jdk1.8.0_45\jre\bin\java.exe # 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: net.almson.util.TestBenchmark.benchmark1 # Run progress: 0.00% complete, ETA 00:00:04 # Fork: 1 of 1 # Warmup Iteration 1: 2.984 us/op # Warmup Iteration 2: 3.007 us/op Iteration 1: 2.844 us/op Iteration 2: 2.832 us/op Result "benchmark1": 2.838 us/op # Run complete. Total time: 00:00:05 Benchmark Mode Cnt Score Error Units TestBenchmark.benchmark1 avgt 2 2.838 us/op Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.255 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Runner.run
restituisce ancheRunResult
oggetti su cui è possibile fare affermazioni, ecc
Questo non è un opzione consigliata per eseguire i test sotto JMH. Test unitari e altri IDE interferiscono con le misurazioni. Fallo direttamente dalla riga di comando. –
@IvanVoroshilin L'ho provato in entrambi i modi e non ho visto differenze nei risultati. Hai un consiglio concreto in quali condizioni questo diventa un problema? –
I risultati sono meno affidabili, è solo una raccomandazione. Elimina i fattori esterni. Ciò interferisce con il microbenchmarking. –