From 73324fa97e504e7a8cce5ae211efca95be4c33e9 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 23 Jul 2014 10:46:57 +0200 Subject: Allow converting junit test to scalameter benchmark Lets start tracking performance! To run benchmarks execute `dotty-bench/test:run` in sbt --- bench/src/test/scala/TestsAsBenchmarks.scala | 61 ++++++++++++++++++++++++++++ project/Build.scala | 50 ++++++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 bench/src/test/scala/TestsAsBenchmarks.scala diff --git a/bench/src/test/scala/TestsAsBenchmarks.scala b/bench/src/test/scala/TestsAsBenchmarks.scala new file mode 100644 index 000000000..a078c9f78 --- /dev/null +++ b/bench/src/test/scala/TestsAsBenchmarks.scala @@ -0,0 +1,61 @@ +package dotty.tools.benchmarks + +import java.lang.annotation.Annotation +import java.lang.reflect.Method + +import org.junit.runner.Request +import org.junit.runner.notification.RunNotifier +import org.scalameter.PerformanceTest.OnlineRegressionReport +import org.scalameter.api._ +import org.scalameter.reporting.RegressionReporter.Tester + +import scala.collection.mutable.ListBuffer + + +abstract class TestsToBenchmarkConverter +(targetClass: Class[_], + filterAnnot: Class[_ <: java.lang.annotation.Annotation] = classOf[org.junit.Test].asInstanceOf[Class[_ <: java.lang.annotation.Annotation]]) + extends OnlineRegressionReport { + + // accept all the results, do not fail + override def tester: Tester = new Tester.Accepter + + override def executor: Executor = LocalExecutor(warmer, aggregator, measurer) + val testNames = getMethodsAnnotatedWith(targetClass, filterAnnot).map(_.getName).sorted + + + val tests = testNames.map{name => + val runner = Request.method(targetClass, name).getRunner + (name, Gen.single("test")(name).map(Request.method(targetClass, _).getRunner))}.toMap + //Gen.enumeration("test")(testNames:_*) + + performance of targetClass.getSimpleName config (Context(reports.resultDir -> "./tmp")) in { + for (test <- testNames) + measure.method(test) in { + using(tests(test)) curve test in { + r => + val dummy = new RunNotifier() + r.run(dummy) + } + } + } + + def getMethodsAnnotatedWith(clazz: Class[_], annotation: Class[_ <: java.lang.annotation.Annotation]): List[Method] = { + val methods = ListBuffer[Method]() + var klass: Class[_] = clazz + while (klass ne classOf[AnyRef]) { + val allMethods = klass.getDeclaredMethods + import scala.collection.JavaConversions._ + for (method <- allMethods) { + if (annotation == null || method.isAnnotationPresent(annotation)) { + val annotInstance: Annotation = method.getAnnotation(annotation) + methods.add(method) + } + } + klass = klass.getSuperclass + } + methods.toList + } +} + +object dotcTests extends TestsToBenchmarkConverter(classOf[dotc.tests]) diff --git a/project/Build.scala b/project/Build.scala index b6ae0c742..60b82e5f9 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1,6 +1,5 @@ +import sbt.Keys._ import sbt._ -import Keys._ -import Process._ object DottyBuild extends Build { @@ -74,4 +73,51 @@ object DottyBuild extends Build { ) lazy val dotty = Project(id = "dotty", base = file("."), settings = defaults) + + lazy val benchmarkSettings = Defaults.defaultSettings ++ Seq( + + // to get Scala 2.11 + resolvers += Resolver.sonatypeRepo("releases"), + + baseDirectory in (Test,run) := (baseDirectory in dotty).value, + + + libraryDependencies ++= Seq("com.storm-enroute" %% "scalameter" % "0.6" % Test, + "com.novocode" % "junit-interface" % "0.11-RC1"), + testFrameworks += new TestFramework("org.scalameter.ScalaMeterFramework"), + + // scalac options + scalacOptions in Global ++= Seq("-feature", "-deprecation", "-language:_"), + + javacOptions ++= Seq("-Xlint:unchecked", "-Xlint:deprecation"), + + fork in Test := true, + parallelExecution in Test := false, + + // http://grokbase.com/t/gg/simple-build-tool/135ke5y90p/sbt-setting-jvm-boot-paramaters-for-scala + javaOptions <++= (dependencyClasspath in Runtime, packageBin in Compile) map { (attList, bin) => + // put the Scala {library, reflect, compiler} in the classpath + val path = for { + file <- attList.map(_.data) + path = file.getAbsolutePath + prefix = if(path.endsWith(".jar")) "p" else "a" + } yield "-Xbootclasspath/"+ prefix +":" + path + // dotty itself needs to be in the bootclasspath + val fullpath = ("-Xbootclasspath/a:" + bin) :: path.toList + // System.err.println("BOOTPATH: " + fullpath) + + val travis_build = // propagate if this is a travis build + if (sys.props.isDefinedAt(TRAVIS_BUILD)) + List(s"-D$TRAVIS_BUILD=${sys.props(TRAVIS_BUILD)}") + else + List() + val res = agentOptions ::: travis_build ::: fullpath + println("Running with javaOptions: " +res) + res + } + ) + + + lazy val benchmarks = Project(id = "dotty-bench", settings = benchmarkSettings, + base = file("bench")) dependsOn(dotty % "compile->test") } -- cgit v1.2.3