Como posso usar benchmarks JMH para Scala junto com sbt?
-
21-12-2019 - |
Pergunta
Eu tentei usar jmh junto com sBT, mas até agora não consegui configurá-lo corretamente para que os benchmarks baseados em .scala funcionem.
Como a combinação Benchmarks baseados em sbt + .java funciona, tentei começar a partir dessa base.Estou usando o sbt 0.13.1.
Benchmarks baseados em .java usando sbt
construir.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")
Para obter um único frasco "gordo" no final, o montagem sbt plugin é necessário:
projeto/montagem.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
Uma referência simples:
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;
}
}
Correndo sbt assembly
fornece esta saída:
$ montagem do sbt
[...]
[info] Compilando 2 fontes Scala e 2 fontes Java para ...
[avisar] aviso:Versão de origem suportada 'RELEASE_6' do processador de anotação 'org.openjdk.jmh.generators.GenerateMicroBenchmarkProcessor' menor que -source '1.8'
[avisar] 1 aviso
[informações] Incluindo:jmh-java-benchmark-archetype-0.5.5.jar
[informações] Incluindo:jmh-generator-bytecode-0.5.5.jar
[informações] Incluindo:jopt-simple-4.6.jar
[informações] Incluindo:jmh-generator-reflection-0.5.5.jar
[informações] Incluindo:jmh-generator-annprocess-0.5.5.jar
[informações] Incluindo:asm-4.2.jar
[informações] Incluindo:commons-math3-3.2.jar
[informações] Incluindo:jmh-core-0.5.5.jar
[informações] Incluindo:scala-library.jar
[...]
[informações] Embalagem /home/scala-2.10/vc/rhaag/scala/scala-benchmark/target/scala-2.10/microbenchmarks.jar ...
e o resultante microbenchmarks.jar
contém tudo o que é necessário para executar os benchmarks:
$ 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
Até agora tudo bem.
Benchmarks Scala usando sbt
A partir dessa base, tentei mudar para benchmarks baseados em .scala:
construir.sbt
Substituindo o arquétipo Java pelo Scala
libraryDependencies += "org.openjdk.jmh" % "jmh-scala-benchmark-archetype" % "0.5.5"
não funciona, pois o download falha.
Isso funciona:
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"
Outra referência simples:
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
}
}
Agora sbt assembly
cria o arquivo jar, mas target/scala-2.10/microbenchmarks.jar#META-INF/MicroBenchmarks
não lista os benchmarks Scala, e estes não são mostrados por java -jar target/scala-2.10/microbenchmarks.jar -l
qualquer.
Recursos:
- JMH com especialista (há um link para um formiga abordagem baseada também)
- Uma página japonesa de onde obtive a configuração inicial do sbt
- JMH com gradle
Como posso integrar o processador JMH (baseado em bytecode) para Scala?Ou de outra perspectiva:Por que o processador JMH (baseado em anotação) é selecionado automaticamente e produz benchmarks baseados em Java?
Solução
Eu implementei um sbt-jmh plugin que realmente funciona: https://github.com/ktoso/sbt-jmh
Atualmente, a construção de benchmarks.jar não é suportada, mas você pode simplesmente digitar run -i 10 .*MyBenchmark.*
e funcionará conforme o esperado (fazendo toda a compilação em várias etapas para você).
Espero que isso ajude, felicidades!