Come posso usare JMH per i benchmark Scala insieme a sbt?
-
21-12-2019 - |
Domanda
Ho provato ad usare jmh insieme a sbt, ma finora non sono riuscito a configurarlo correttamente in modo che .i benchmark basati su scala funzionano.
Come la combinazione sbt + .benchmark basati su java funziona, ho provato a partire da quella base.Sto usando sbt 0.13.1.
.benchmark basati su java che utilizzano sbt
costruire.sbt
import AssemblyKeys._
name := "scala-benchmark"
version := "1.0"
scalaVersion := "2.10.3"
scalacOptions += "-deprecation"
libraryDependencies += "org.openjdk.jmh" % "jmh-core" % "0.5.5"
libraryDependencies += "org.openjdk.jmh" % "jmh-java-benchmark-archetype" % "0.5.5"
libraryDependencies += "org.openjdk.jmh" % "jmh-generator-annprocess" % "0.5.5"
libraryDependencies += "org.openjdk.jmh" % "jmh-generator-bytecode" % "0.5.5"
assemblySettings
jarName in assembly := "microbenchmarks.jar"
test in assembly := {}
mainClass in assembly := Some("org.openjdk.jmh.Main")
Per ottenere un singolo barattolo "grasso" alla fine, l' sbt-assemblaggio il plugin è richiesto:
progetto / montaggio.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
Un semplice benchmark:
src / main / java / app / benchmark / java / benchmark2 / Benchmark2.Java
package app.benchmark.java.benchmark2;
import org.openjdk.jmh.annotations.GenerateMicroBenchmark;
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 Benchmark2 {
@GenerateMicroBenchmark
public int run() {
int result = 0;
for (int i = 0; i < 10; i++) {
result += i * i;
}
return result;
}
}
Esecuzione sbt assembly
dà questo output:
assembly assemblea di sbt
[...]
[info] Compilazione di 2 sorgenti Scala e 2 sorgenti Java ...
[warn] attenzione:Versione sorgente supportata 'RELEASE_6' dal processore di annotazione ' org.apriscatole.jmh.generatore.generatemicrobenchmarkprocessore 'minore di-fonte '1.8'
[warn] 1 avvertimento
[info] Compreso:jmh-java-benchmark-archetype-0.5.5.vaso
[info] Compreso:jmh-generator-bytecode-0.5.5.vaso
[info] Compreso:jopt-semplice-4.6.vaso
[info] Compreso:jmh-generator-reflection-0.5.5.vaso
[info] Compreso:jmh-generator-annprocess-0.5.5.vaso
[info] Compreso:asm-4.2.vaso
[info] Compreso:commons-math3-3.2.vaso
[info] Compreso:jmh-nucleo-0.5.5.vaso
[info] Compreso:scala-biblioteca.vaso
[...]
[info] Packaging/home / scala-2.10 / vc / rhaag/scala/scala-benchmark/target/scala-2.10 / microbenchmarks.vaso ...
e il risultato microbenchmarks.jar
contiene tutto il necessario per eseguire i benchmark:
$ java -jar target/scala-2.10/microbenchmarks.jar -wi 3 -i 3 -f 1 app.benchmark.java.benchmark2.Benchmark2.run
[...]
Benchmark Mode Samples Mean Mean error Units
a.b.j.b.Benchmark2.run thrpt 3 607555,968 70243,275 ops/ms
Fin qui tutto bene.
Benchmark Scala utilizzando sbt
Da quella base ho cercato di passare a .benchmark basati su scala:
costruire.sbt
Sostituire l'archetipo Java con quello Scala
libraryDependencies += "org.openjdk.jmh" % "jmh-scala-benchmark-archetype" % "0.5.5"
non funziona, come il download non riesce.
Questo funziona:
libraryDependencies += "org.openjdk.jmh" % "jmh-scala-benchmark-archetype" % "0.5.5" from "http://repo1.maven.org/maven2/org/openjdk/jmh/jmh-scala-benchmark-archetype/0.5.5/jmh-scala-benchmark-archetype-0.5.5.jar"
Un altro semplice benchmark:
src / main / scala / app / benchmark / scala / benchmark2 / Benchmark2.scala
package app.benchmark.scala.benchmark2
import org.openjdk.jmh.annotations.GenerateMicroBenchmark
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
class Benchmark2 {
@GenerateMicroBenchmark
def run() = {
Seq.range(0, 10).map(i => i * i).sum
}
}
Ora sbt assembly
crea il file jar, ma target/scala-2.10/microbenchmarks.jar#META-INF/MicroBenchmarks
non elenca i benchmark Scala, e questi non sono mostrati da java -jar target/scala-2.10/microbenchmarks.jar -l
neanche.
Resources:
- JMH con maven (c'è un link a un formica anche l'approccio basato)
- Una pagina giapponese da cui ho ottenuto la configurazione sbt iniziale
- JMH con gradle
Come posso integrare il processore JMH (basato su bytecode) per Scala?O da un'altra prospettiva:Perché il processore JMH (basato su annotazioni) viene rilevato automaticamente e produce benchmark basati su Java?
Soluzione
Ho implementato un sbt-jmh plugin che funziona davvero: https://github.com/ktoso/sbt-jmh
Attualmente costruire benchmark.jar non è supportato, ma puoi semplicemente digitare run -i 10 .*MyBenchmark.*
e funzionerà come previsto (facendo tutta la compilazione multi-step per te).
Spero che questo aiuti, salute!