-
Notifications
You must be signed in to change notification settings - Fork 51
/
RunProfiler.scala
75 lines (63 loc) · 2.59 KB
/
RunProfiler.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package sjsonnet
import java.io.StringWriter
object RunProfiler extends App {
val parser = mainargs.ParserForClass[Config]
val config = parser.constructEither(MainBenchmark.mainArgs, autoPrintHelpAndExit = None).getOrElse(???)
val file = config.file
val wd = os.pwd
val path = OsPath(os.Path(file, wd))
val parseCache = new DefaultParseCache
val interp = new Interpreter(
Map.empty[String, String],
Map.empty[String, ujson.Value],
OsPath(wd),
importer = SjsonnetMain.resolveImport(config.jpaths.map(os.Path(_, wd)).map(OsPath(_)), None),
parseCache = parseCache
) {
override def createEvaluator(resolver: CachedResolver, extVars: String => Option[Expr], wd: Path,
settings: Settings, warn: Error => Unit): Evaluator =
new ProfilingEvaluator(resolver, extVars, wd, settings, warn)
}
val profiler = interp.evaluator.asInstanceOf[ProfilingEvaluator]
def run(): Long = {
val renderer = new Renderer(new StringWriter, indent = 3)
val start = interp.resolver.read(path).get
val t0 = System.nanoTime()
interp.interpret0(start, path, renderer).getOrElse(???)
System.nanoTime() - t0
}
println("\nWarming up...")
profiler.clear()
for(i <- 1 to 10) run()
println("\nProfiling...")
profiler.clear()
val total = (for(i <- 1 to 5) yield run()).sum
val roots = parseCache.valuesIterator.map(_.getOrElse(???)).map(_._1).toSeq
roots.foreach(profiler.accumulate)
println(s"\nTop 20 by time:")
profiler.all.sortBy(-_.time).take(20).foreach { b => show(b.time, b, "- ", false) }
val cutoff = 0.02
println(s"\nTrees with >= $cutoff time:")
showAll(roots, "")
def showAll(es: Seq[Expr], indent: String) = {
val timed = es.iterator.map(profiler.get).filter { case b =>
b.totalTime.toDouble / total.toDouble >= cutoff
}.toSeq.sortBy(-_.time)
timed.foreach { case b => show(b.totalTime, b, indent, true) }
}
def show(time: Long, box: profiler.ExprBox, indent: String, rec: Boolean): Unit = {
println(s"$indent${time/1000000L}ms ${box.name} ${box.prettyPos}")
if(rec) showAll(box.children, indent + " ")
}
def show(n: String, bs: Seq[profiler.Box]): Unit = {
println(n)
bs.filter(_.count > 0).sortBy(-_.time).foreach { ob =>
val avg = if(ob.count == 0) 0 else ob.time / ob.count
println(s"- ${ob.time/1000000L}ms\t${ob.count}\t${avg}ns\t${ob.name}")
}
}
show(s"\nBinary operators:", profiler.binaryOperators())
show(s"\nUnary operators:", profiler.unaryOperators())
show(s"\nBuilt-in functions:", profiler.builtins())
show(s"\nExpr types:", profiler.exprTypes())
}