Was genau ist der Unterschied zwischen AverageTime und SingleShotTime im Java Microbenchmark Harness?Java

Java-Forum
Anonymous
 Was genau ist der Unterschied zwischen AverageTime und SingleShotTime im Java Microbenchmark Harness?

Post by Anonymous »

Ich glaube, ich verstehe den Unterschied zwischen AverageTime und Throughput.
Sagen wir, wir haben eine Methode mit den folgenden Anmerkungen:

Code: Select all

@Benchmark
@Fork(value = 1, warmups = 0)
@Measurement(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
Wenn ich @BenchmarkMode(Mode.AverageTime) verwende, startet JMH einen Fork (weil @Fork(value = 1)), führt eine Iteration durch (weil @Measurement(iterations = 1)) und führt die Methode fooBenchmark so oft aus, wie die Aufrufe abgeschlossen werden können (JMH nennt sie Level.Invocation in). org.openjdk.jmh.annotations-Paket) vollständig in mindestens einer Sekunde (weil @Measurement(time = 1, timeUnit = TimeUnit.SECONDS)).
Wir teilen die verstrichene Zeit durch Aufrufe.
Dies ergibt die durchschnittliche Zeit pro Aufruf.
Wenn ich @BenchmarkMode(Mode.Throughput) verwende, teilen wir die Anzahl der abgeschlossenen Aufrufe nach verstrichener Zeit.
Das gibt uns den Durchsatz.
Sagen wir, wir haben eine Benchmark-Klasse mit einem Status Foo:

Code: Select all

@State(Scope.Benchmark)
internal open class FooBenchmark {
class Foo {
private val values = mutableListOf()

fun add() = values.add(values.size.toString())

fun size() = values.size
}

private val foo = Foo()

@Benchmark
@Fork(value = 1, warmups = 0)
@Measurement(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@BenchmarkMode(Mode.SingleShotTime)
fun fooBenchmark(hole: Blackhole) {
check(foo.size() == 0)
foo.add()
check(foo.size() == 1)
hole.consume(foo)
}
}
Wenn ich @BenchmarkMode(Mode.SingleShotTime) verwende, erwarte ich, dass JMH genau einen Aufruf durchführt und die Zeit genau dieses einen Aufrufs misst.
Aber für mich ruft JMH für SingleShotTime die Methode fooBenchmark mehrmals auf.
1 Fork, 1 Iteration, aber mehrere Aufrufe.
Und es verwendet dieselbe Instanz von FooBenchmark-Klasse in verschiedenen Threads.
Dies führt zu einem Konflikt beim Zugriff auf den foo-Status.
Dies ist nur ein Beispiel dafür, wie definitiv mehrere Aufrufe stattfinden. Ich muss NICHT auf Daten aus verschiedenen Threads zugreifen.
Ich verstehe nicht, wie die einzelnen JMH-Modi funktionieren? Oder habe ich den SingleShotTime-Modus falsch konfiguriert?
Das erzeugt JMH beim Ausführen der Aufgabe:

Code: Select all

> Task :lib:runBenchmark
# Detecting actual CPU count: 8 detected
# JMH version: 1.37
# VM version: JDK 19.0.1, OpenJDK 64-Bit Server VM, 19.0.1+10-21
# VM invoker: /opt/jdk-19.0.1/bin/java
# VM options: -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 
# Measurement: 1 iterations, 1 s each
# Timeout: 10000 ms per iteration
# Threads: 8 threads
# Benchmark mode: Single shot invocation time
# Benchmark: org.kepocnhh.jmh.FooBenchmark.fooBenchmark

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post