Skip to content

Commit e79d1cd

Browse files
committed
Better benchmark and Stats infrastructure
- Allow to specify the number of `#compilers` to run and the number of #runs per compiler. - Allow to specify with #wait-after a run after which we ask for a prompt. Useful for precise profiling. - Fix bug in Stats that prevented printing of detailed statistics
1 parent 4a11252 commit e79d1cd

File tree

3 files changed

+26
-23
lines changed

3 files changed

+26
-23
lines changed

compiler/src/dotty/tools/dotc/Bench.scala

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,22 @@ import scala.annotation.internal.sharable
1414
object Bench extends Driver:
1515

1616
@sharable private var numRuns = 1
17-
18-
private def ntimes(n: Int)(op: => Reporter): Reporter =
19-
(0 until n).foldLeft(emptyReporter)((_, _) => op)
20-
17+
@sharable private var numCompilers = 1
18+
@sharable private var waitAfter = -1
19+
@sharable private var curCompiler = 0
2120
@sharable private var times: Array[Int] = _
2221

2322
override def doCompile(compiler: Compiler, files: List[AbstractFile])(using Context): Reporter =
24-
times = new Array[Int](numRuns)
2523
var reporter: Reporter = emptyReporter
2624
for i <- 0 until numRuns do
25+
val curRun = curCompiler * numRuns + i
2726
val start = System.nanoTime()
2827
reporter = super.doCompile(compiler, files)
29-
times(i) = ((System.nanoTime - start) / 1000000).toInt
30-
println(s"time elapsed: ${times(i)}ms")
31-
if ctx.settings.Xprompt.value then
28+
times(curRun) = ((System.nanoTime - start) / 1000000).toInt
29+
println(s"time elapsed: ${times(curRun)}ms")
30+
if ctx.settings.Xprompt.value || waitAfter == curRun + 1 then
3231
print("hit <return> to continue >")
3332
System.in.nn.read()
34-
println()
3533
reporter
3634

3735
def extractNumArg(args: Array[String], name: String, default: Int = 1): (Int, Array[String]) = {
@@ -42,20 +40,26 @@ object Bench extends Driver:
4240

4341
def reportTimes() =
4442
val best = times.sorted
45-
val measured = numRuns / 3
43+
val measured = numCompilers * numRuns / 3
4644
val avgBest = best.take(measured).sum / measured
4745
val avgLast = times.reverse.take(measured).sum / measured
48-
println(s"best out of $numRuns runs: ${best(0)}")
46+
println(s"best out of ${numCompilers * numRuns} runs: ${best(0)}")
4947
println(s"average out of best $measured: $avgBest")
5048
println(s"average out of last $measured: $avgLast")
5149

52-
override def process(args: Array[String], rootCtx: Context): Reporter =
50+
override def process(args: Array[String]): Reporter =
5351
val (numCompilers, args1) = extractNumArg(args, "#compilers")
5452
val (numRuns, args2) = extractNumArg(args1, "#runs")
53+
val (waitAfter, args3) = extractNumArg(args2, "#wait-after", -1)
54+
this.numCompilers = numCompilers
5555
this.numRuns = numRuns
56+
this.waitAfter = waitAfter
57+
this.times = new Array[Int](numCompilers * numRuns)
5658
var reporter: Reporter = emptyReporter
57-
for i <- 0 until numCompilers do
58-
reporter = super.process(args2, rootCtx)
59+
curCompiler = 0
60+
while curCompiler < numCompilers do
61+
reporter = super.process(args3)
62+
curCompiler += 1
5963
reportTimes()
6064
reporter
6165

compiler/src/dotty/tools/dotc/Driver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class Driver {
171171
* the other overloads without worrying about breaking compatibility
172172
* with sbt.
173173
*/
174-
final def process(args: Array[String]): Reporter =
174+
def process(args: Array[String]): Reporter =
175175
process(args, null: Reporter | Null, null: interfaces.CompilerCallback | Null)
176176

177177
/** Entry point to the compiler using a custom `Context`.

compiler/src/dotty/tools/dotc/util/Stats.scala

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,14 @@ import collection.mutable
5555
}
5656

5757
def maybeMonitored[T](op: => T)(using Context): T =
58-
if (ctx.settings.YdetailedStats.value && hits.nonEmpty) {
58+
if ctx.settings.YdetailedStats.value then
5959
monitored = true
6060
try op
61-
finally {
62-
aggregate()
63-
println()
64-
println(hits.toList.sortBy(_._2).map{ case (x, y) => s"$x -> $y" } mkString "\n")
65-
hits.clear()
66-
}
67-
}
61+
finally
62+
if hits.nonEmpty then
63+
aggregate()
64+
println()
65+
println(hits.toList.sortBy(_._2).map{ case (x, y) => s"$x -> $y" } mkString "\n")
66+
hits.clear()
6867
else op
6968
}

0 commit comments

Comments
 (0)