Как я могу использовать JMH для тестов Scala вместе с sbt?

Я попытался использовать вместе с , но до сих пор у меня есть не удалось настроить его должным образом, чтобы тесты на основе scala работали.

В качестве совпадающих тестов на основе sbt +.java, я попытался начать с этой базы. Я использую sbt 0.13.1.


. Тесты на основе Java с использованием sbt

build.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")

Чтобы получить единую "жирную" банку в конце, необходим плагин sbt-assembly:

Проект /assembly.sbt

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")

Простой критерий:

SRC/главная/Java/приложение/тест/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;
    }
}

Запуск sbt assembly дает этот вывод:

$sbt assembly
[...]
[info] Компиляция 2 Scala источников и 2 источников Java для... Предупреждение [предупреждение]: поддерживаемая исходная версия "RELEASE_6" из обработчика аннотации "org.openjdk.jmh.generators.GenerateMicroBenchmarkProcessor" меньше, чем "источник" 1,8 "
[предупреждение] 1 предупреждение
[info] В том числе: jmh-java-benchmark-archetype-0.5.5.jar
[info] В том числе: jmh-generator-bytecode-0.5.5.jar
[info] В том числе: jopt-simple-4.6.jar
[info] В том числе: jmh-generator-reflection-0.5.5.jar
[info] В том числе: jmh-generator-annprocess-0.5.5.jar
[info] В том числе: asm-4.2.jar
[info] В том числе: commons-math3-3.2.jar
[info] В том числе: jmh-core-0.5.5.jar
[info] В том числе: scala -library.jar
[...]
[info] Упаковка /home/ scala-2.10/vc/rhaag/scala/scala-benchmark/target/scala-2.10/microbenchmarks.jar...

и итоговый microbenchmarks.jar содержит все необходимое для запуска тестов:

$ 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 

Пока все хорошо.


Scala с использованием sbt

С этой базы я попытался переключиться на тесты на основе .scala:

build.sbt

Замена архетипа Java на Scala one

libraryDependencies += "org.openjdk.jmh" % "jmh-scala-benchmark-archetype" % "0.5.5"

не работает, так как загрузка не выполняется.

Это работает:

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"

Еще один простой тест:

SRC/главная/ scala/приложение/тест/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
  }
}

Теперь sbt assembly создает файл jar, но target/scala-2.10/microbenchmarks.jar#META-INF/MicroBenchmarks не перечисляет тесты Scala, и они не отображаются java -jar target/scala-2.10/microbenchmarks.jar -l.


Ресурсы

Как я могу интегрировать JMH-процессор на основе байт-кода для Scala? Или с другой стороны: почему (основанный на аннотации) JMH-процессор автоматически подбирается и производит тесты на основе Java?

Ответ 1

Я реализовал плагин sbt-jmh, который действительно работает: https://github.com/ktoso/sbt-jmh

В настоящее время создание benchmarks.jar не поддерживается, но вы можете просто ввести run -i 10 .*MyBenchmark.*, и он будет работать как ожидается (сделав для вас многоступенчатую компиляцию).

Надеюсь, это поможет, ура!