Java Language
benchmarks
Zoeken…
Invoering
Prestatiebenchmarks schrijven in Java is niet zo eenvoudig als System.currentTimeMillis()
in het begin en aan het einde krijgen en het verschil berekenen. Om geldige prestatiebenchmarks te schrijven, moet men de juiste hulpmiddelen gebruiken.
Eenvoudig JMH-voorbeeld
Een van de hulpmiddelen voor het schrijven van goede benchmarktests is JMH . Laten we zeggen dat we de prestaties van het zoeken naar een element in HashSet
willen vergelijken met TreeSet
.
De eenvoudigste manier om JHM in uw project te krijgen - is door maven en schaduw plug-ins te gebruiken. Je kunt ook pom.xml
uit JHM-voorbeelden .
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.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>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.18</version>
</dependency>
</dependencies>
Hierna moet u benchmarkklasse zelf schrijven:
package benchmark;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
@State(Scope.Thread)
public class CollectionFinderBenchmarkTest {
private static final int SET_SIZE = 10000;
private Set<String> hashSet;
private Set<String> treeSet;
private String stringToFind = "8888";
@Setup
public void setupCollections() {
hashSet = new HashSet<>(SET_SIZE);
treeSet = new TreeSet<>();
for (int i = 0; i < SET_SIZE; i++) {
final String value = String.valueOf(i);
hashSet.add(value);
treeSet.add(value);
}
stringToFind = String.valueOf(new Random().nextInt(SET_SIZE));
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void testHashSet(Blackhole blackhole) {
blackhole.consume(hashSet.contains(stringToFind));
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void testTreeSet(Blackhole blackhole) {
blackhole.consume(treeSet.contains(stringToFind));
}
}
Houd dit blackhole.consume()
in gedachten, we komen er later op terug. We hebben ook de hoofdklasse nodig voor het uitvoeren van benchmark:
package 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 BenchmarkMain {
public static void main(String[] args) throws RunnerException {
final Options options = new OptionsBuilder()
.include(CollectionFinderBenchmarkTest.class.getSimpleName())
.forks(1)
.build();
new Runner(options).run();
}
}
En we zijn er helemaal klaar voor. We moeten alleen het mvn package
(het maakt benchmarks.jar
in uw /target
) en onze benchmark-test uitvoeren:
java -cp target/benchmarks.jar benchmark.BenchmarkMain
En na wat opwarm- en berekeningsiteraties, zullen we onze resultaten hebben:
# Run complete. Total time: 00:01:21
Benchmark Mode Cnt Score Error Units
CollectionFinderBenchmarkTest.testHashSet avgt 20 9.940 ± 0.270 ns/op
CollectionFinderBenchmarkTest.testTreeSet avgt 20 98.858 ± 13.743 ns/op
Over dat blackhole.consume()
. Als uw berekeningen de status van uw toepassing niet veranderen, zal Java deze waarschijnlijk gewoon negeren. Dus om dit te voorkomen, kunt u uw benchmarkmethoden een waarde laten retourneren of het Blackhole
object gebruiken om het te consumeren.
Meer informatie over het schrijven van juiste benchmarks vindt u in de blog van Aleksey Shipilëv , in de blog van Jacob Jenkov en in de blog over Java-prestaties: 1 , 2 .