Skip to content

Commit 6989dd9

Browse files
authored
Merge pull request #31 from olafurpg/dotty2
Compile benchmark with Dotty, fixes #29.
2 parents 84a3854 + dd00264 commit 6989dd9

File tree

8 files changed

+132
-51
lines changed

8 files changed

+132
-51
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ language: scala
33
env:
44
global:
55

6-
script: sbt test:compile "hot -psource=scalap -w1 -f1" "micro/jmh:run -w1 -f1"
6+
script: sbt testAll
77

88
jdk:
99
- oraclejdk8

build.sbt

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,21 @@ name := "compiler-benchmark"
22

33
version := "1.0-SNAPSHOT"
44

5-
scalaVersion in ThisBuild := "2.11.8"
5+
def scala211 = "2.11.11"
6+
def dottyLatest = "0.2.0-RC1"
7+
scalaVersion in ThisBuild := scala211
8+
9+
commands += Command.command("testAll") { s =>
10+
"test:compile" ::
11+
"compilation/test" ::
12+
"hot -psource=scalap -wi 1 -i 1 -f1" ::
13+
s"++$dottyLatest" ::
14+
"compilation/test" ::
15+
"hot -psource=vector -wi 1 -i 1 -f1" ::
16+
s"++$scala211" ::
17+
"micro/jmh:run -w1 -f1" ::
18+
s
19+
}
620

721
resolvers += "scala-integration" at "https://scala-ci.typesafe.com/artifactory/scala-integration/"
822

@@ -36,8 +50,17 @@ lazy val compilation = addJmh(project).settings(
3650
// We should be able to switch this project to a broad range of Scala versions for comparative
3751
// benchmarking. As such, this project should only depend on the high level `MainClass` compiler API.
3852
description := "Black box benchmark of the compiler",
39-
libraryDependencies += scalaOrganization.value % "scala-compiler" % scalaVersion.value,
40-
mainClass in (Jmh, run) := Some("scala.bench.ScalacBenchmarkRunner")
53+
libraryDependencies += {
54+
if (isDotty.value) "ch.epfl.lamp" %% "dotty-compiler" % scalaVersion.value
55+
else scalaOrganization.value % "scala-compiler" % scalaVersion.value
56+
},
57+
crossScalaVersions := List(scala211, dottyLatest),
58+
unmanagedSourceDirectories.in(Compile) +=
59+
sourceDirectory.in(Compile).value / (if (isDotty.value) "dotc" else "scalac"),
60+
mainClass in (Jmh, run) := Some("scala.bench.ScalacBenchmarkRunner"),
61+
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % Test,
62+
testOptions in Test += Tests.Argument(TestFrameworks.JUnit),
63+
fork in (Test, test) := true // jmh scoped tasks run with fork := true.
4164
).settings(addJavaOptions).dependsOn(infrastructure)
4265

4366
lazy val micro = addJmh(project).settings(
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package scala.tools.benchmark
2+
3+
import java.io.File
4+
import scala.tools.nsc.BaseBenchmarkDriver
5+
import dotty.tools.dotc.core.Contexts.ContextBase
6+
7+
trait BenchmarkDriver extends BaseBenchmarkDriver {
8+
def compileImpl(): Unit = {
9+
implicit val ctx = new ContextBase().initialCtx.fresh
10+
ctx.setSetting(ctx.settings.usejavacp, true)
11+
if (depsClasspath != null) {
12+
ctx.setSetting(ctx.settings.classpath,
13+
depsClasspath.mkString(File.pathSeparator))
14+
}
15+
ctx.setSetting(ctx.settings.migration, true)
16+
ctx.setSetting(ctx.settings.d, tempDir.getAbsolutePath)
17+
ctx.setSetting(ctx.settings.language, List("Scala2"))
18+
val compiler = new dotty.tools.dotc.Compiler
19+
val reporter = dotty.tools.dotc.Bench.doCompile(compiler, allArgs)
20+
assert(!reporter.hasErrors)
21+
}
22+
}

compilation/src/main/scala/scala/tools/nsc/ScalacBenchmark.scala

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,23 @@ import org.openjdk.jmh.annotations.Mode._
1212
import org.openjdk.jmh.annotations._
1313

1414
import scala.collection.JavaConverters._
15+
import scala.tools.benchmark.BenchmarkDriver
16+
17+
trait BaseBenchmarkDriver {
18+
def source: String
19+
def extraArgs: String
20+
def extras: List[String] = if (extraArgs != null && extraArgs != "") extraArgs.split('|').toList else Nil
21+
def allArgs: List[String] = compilerArgs ++ extras ++ sourceFiles
22+
def corpusVersion: String
23+
def depsClasspath: String
24+
def tempDir: File
25+
def corpusSourcePath: Path
26+
def compilerArgs: List[String]
27+
def sourceFiles: List[String]
28+
}
1529

1630
@State(Scope.Benchmark)
17-
class ScalacBenchmark {
31+
class ScalacBenchmark extends BenchmarkDriver {
1832
@Param(value = Array())
1933
var source: String = _
2034

@@ -26,54 +40,23 @@ class ScalacBenchmark {
2640
@Param(value = Array("latest"))
2741
var corpusVersion: String = _
2842

29-
var driver: Driver = _
30-
3143
var depsClasspath: String = _
3244

33-
def compileImpl(): Unit = {
34-
val (compilerArgs, sourceFiles) =
35-
if (source.startsWith("@")) (List(source), List[String]())
36-
else {
37-
import scala.collection.JavaConverters._
38-
val allFiles = Files.walk(findSourceDir, FileVisitOption.FOLLOW_LINKS).collect(Collectors.toList[Path]).asScala.toList
39-
val files = allFiles.filter(f => {
40-
val name = f.getFileName.toString
41-
name.endsWith(".scala") || name.endsWith(".java")
42-
}).map(_.toAbsolutePath.normalize.toString).toList
43-
(List[String](), files)
44-
}
45-
46-
// MainClass is copy-pasted from compiler for source compatibility with 2.10.x - 2.13.x
47-
class MainClass extends Driver with EvalLoop {
48-
def resident(compiler: Global): Unit = loop { line =>
49-
val command = new CompilerCommand(line split "\\s+" toList, new Settings(scalacError))
50-
compiler.reporter.reset()
51-
new compiler.Run() compile command.files
52-
}
53-
54-
override def newCompiler(): Global = Global(settings, reporter)
55-
56-
override protected def processSettingsHook(): Boolean = {
57-
if (source == "scala")
58-
settings.sourcepath.value = Paths.get(s"../corpus/$source/$corpusVersion/library").toAbsolutePath.normalize.toString
59-
else
60-
settings.usejavacp.value = true
61-
settings.outdir.value = tempDir.getAbsolutePath
62-
settings.nowarn.value = true
63-
if (depsClasspath != null)
64-
settings.processArgumentString(s"-cp $depsClasspath")
65-
true
66-
}
45+
def compilerArgs: List[String] = if (source.startsWith("@")) source :: Nil else Nil
46+
47+
def sourceFiles: List[String] =
48+
if (source.startsWith("@")) Nil
49+
else {
50+
import scala.collection.JavaConverters._
51+
val allFiles = Files.walk(findSourceDir, FileVisitOption.FOLLOW_LINKS).collect(Collectors.toList[Path]).asScala.toList
52+
val files = allFiles.filter(f => {
53+
val name = f.getFileName.toString
54+
name.endsWith(".scala") || name.endsWith(".java")
55+
}).map(_.toAbsolutePath.normalize.toString)
56+
files
6757
}
68-
val driver = new MainClass
69-
70-
val extras = if (extraArgs != null && extraArgs != "") extraArgs.split('|').toList else Nil
71-
val allArgs = compilerArgs ++ extras ++ sourceFiles
72-
driver.process(allArgs.toArray)
73-
assert(!driver.reporter.hasErrors)
74-
}
7558

76-
private var tempDir: File = null
59+
var tempDir: File = null
7760

7861
// Executed once per fork
7962
@Setup(Level.Trial) def initTemp(): Unit = {
@@ -86,7 +69,7 @@ class ScalacBenchmark {
8669
BenchmarkUtils.deleteRecursive(tempDir.toPath)
8770
}
8871

89-
private def corpusSourcePath = Paths.get(s"../corpus/$source/$corpusVersion")
72+
def corpusSourcePath: Path = Paths.get(s"../corpus/$source/$corpusVersion")
9073

9174
@Setup(Level.Trial) def initDepsClasspath(): Unit = {
9275
val classPath = BenchmarkUtils.initDeps(corpusSourcePath)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package scala.tools.benchmark
2+
3+
import java.nio.file._
4+
import scala.tools.nsc._
5+
6+
trait BenchmarkDriver extends BaseBenchmarkDriver {
7+
def compileImpl(): Unit = {
8+
// MainClass is copy-pasted from compiler for source compatibility with 2.10.x - 2.13.x
9+
class MainClass extends Driver with EvalLoop {
10+
def resident(compiler: Global): Unit = loop { line =>
11+
val command = new CompilerCommand(line split "\\s+" toList, new Settings(scalacError))
12+
compiler.reporter.reset()
13+
new compiler.Run() compile command.files
14+
}
15+
16+
override def newCompiler(): Global = Global(settings, reporter)
17+
18+
override protected def processSettingsHook(): Boolean = {
19+
if (source == "scala")
20+
settings.sourcepath.value = Paths.get(s"../corpus/$source/$corpusVersion/library").toAbsolutePath.normalize.toString
21+
else
22+
settings.usejavacp.value = true
23+
settings.outdir.value = tempDir.getAbsolutePath
24+
settings.nowarn.value = true
25+
if (depsClasspath != null)
26+
settings.processArgumentString(s"-cp $depsClasspath")
27+
true
28+
}
29+
}
30+
val driver = new MainClass
31+
driver.process(allArgs.toArray)
32+
assert(!driver.reporter.hasErrors)
33+
}
34+
35+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package scala.tools.benchmark
2+
3+
import scala.tools.nsc.ScalacBenchmark
4+
import org.junit.Test
5+
6+
class BenchmarkTest {
7+
@Test def compilesOK() = {
8+
val bench = new ScalacBenchmark
9+
bench.source = "../corpus/vector"
10+
bench.corpusVersion = "latest"
11+
bench.initTemp()
12+
bench.compileImpl()
13+
bench.clearTemp()
14+
}
15+
}

corpus/vector/fb04376/Vector.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ override def companion: GenericCompanion[Vector] = Vector
8282

8383
override def lengthCompare(len: Int): Int = length - len
8484

85-
private[collection] final def initIterator[B >: A](s: VectorIterator[B]) {
85+
private[collection] final def initIterator[B >: A](s: VectorIterator[B]): Unit = {
8686
s.initFrom(this)
8787
if (dirty) s.stabilize(focus)
8888
if (s.depth > 1) s.gotoPos(startIndex, startIndex ^ focus)

project/plugins.sbt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ logLevel := Level.Warn
33

44
// sbt-jmh plugin - pulls in JMH dependencies too
55
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.25")
6+
7+
// sbt-dotty plugin - to support `scalaVersion := "0.x"`
8+
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.1.2")

0 commit comments

Comments
 (0)