Skip to content

Commit 8ab0468

Browse files
committed
JMH benchmarks working, and take less time than forever.
1 parent 00977b8 commit 8ab0468

File tree

1 file changed

+82
-29
lines changed

1 file changed

+82
-29
lines changed

benchmark/src/main/scala/bench/CodeGen.scala

Lines changed: 82 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ object Generator {
2222
val parname = annotated.filterNot(_ contains "*").map(_.takeWhile(_.isLetter)).toSet
2323
val sqnname = names.filterNot(parname).toSet union names.filterNot(nojname).toSet
2424
val ordname = annotated.filterNot(_ contains "!").map(_.takeWhile(_.isLetter)).toSet
25+
val jmhsizes = Array(10, 10000) // JMH takes FOREVER, so we're lucky to get two sizes.
2526

2627
def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = {
2728
try {
@@ -57,29 +58,30 @@ object Generator {
5758
pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" )
5859
allops.foreach{ case (o, t, fs) =>
5960
names.foreach{ n =>
60-
pr( s" { // Scope for operations $o collection $n")
61-
pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" )
61+
pr( s" { // Scope for operations $o collection $n")
62+
pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" )
6263
parsefs(fs).foreach{ case (f, pf, ord) =>
6364
if (ordname(n) || !ord) {
64-
pr( """ for (i <- 0 until m) {""")
65-
pr( s" val z = $o.$f(x.arr.c$t(i))")
65+
pr( """ for (i <- 0 until m) {""")
66+
pr( s" val z = $o.$f(x.arr.c$t(i))")
6667
if (nojname(n)) {
67-
pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)");
68-
pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)")
68+
pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)");
69+
pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)")
6970
}
7071
if (sqnname(n)) {
71-
pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)")
72+
pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)")
7273
if (nojname(n))
73-
pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)")
74+
pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)")
7475
}
7576
if (parname(n) && pf.isDefined) {
76-
pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)")
77+
pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)")
7778
if (nojname(n))
78-
pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)")
79+
pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)")
7980
}
80-
pr( s" }")
81+
pr( s" }")
8182
}
8283
}
84+
pr( s" x = null // Allow GC" )
8385
pr( s" } // End scope for operations $o collection $n")
8486
}
8587
}
@@ -93,7 +95,7 @@ object Generator {
9395
}
9496
}
9597

96-
def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]]) {
98+
def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]] = None) {
9799
val q = "\""
98100
if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath)
99101
writeTo(target){ pr =>
@@ -103,52 +105,56 @@ object Generator {
103105
pr( """import scala.compat.java8.StreamConverters._""")
104106
pr( """import ichi.bench.Thyme""")
105107
pr( """""")
106-
pr( """object Agreement {""")
108+
pr( """object ThymeBench {""")
107109
pr( """ def run() {""")
108110
pr( """ val th = Thyme.warmed()""")
109111
pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" )
110112
pr( """ def timings[A](x: bench.generate.Things, op: Int => A, name: String) {""")
111113
pr( """ val ts = new collection.mutable.ArrayBuffer[(Double, Double, Double)]""")
114+
pr( """ val discard = th.clock(op(m-1))(_ => ()) // Init collections""")
112115
pr( """ for (i <- 0 until m) {""")
116+
pr( """ println(name + i)""")
113117
pr( """ val b = Thyme.Benched.empty""")
114118
pr( """ val a = th.bench(op(i))(b)""")
115119
pr( """ if (a == null) ts += ((Double.NaN, Double.NaN, Double.NaN))""")
116-
pr( """ else ts += ((b.runtime * 1e6, b.runtimeCI95._1 * 1e6, b.runtimeCI95._2 * 1e6)""")
120+
pr( """ else ts += ((""")
121+
pr( """ b.runtime * 1e6, b.runtimeCI95._1 * 1e6, b.runtimeCI95._2 * 1e6""")
122+
pr( """ ))""")
117123
pr( """ }""")
118124
pr( """ val sb = new StringBuilder""")
119-
pr( """ sb ++= name + $q: $q""")
120-
pr( """ if (sb.length < 36) sb ++= $q $q * (36 - sb.length)""")
125+
pr( """ sb ++= name + ":" """)
126+
pr( """ if (sb.length < 16) sb ++= " " * (16 - sb.length)""")
121127
pr( """ ts.foreach{ case (c, lo, hi) =>""")
122-
pr( """ sb ++= $q $q""")
123-
pr( """ sb ++= ${q}12.4f${q}.format(c)""")
124-
pr( """ sb ++= ${q}12.4f${q}.format(lo)""")
125-
pr( """ sb ++= ${q}12.4f${q}.format(hi)""")
128+
pr( """ sb ++= " " """)
129+
pr( """ sb ++= " %11.4f".format(c)""")
130+
pr( """ sb ++= " %11.4f".format(lo)""")
131+
pr( """ sb ++= " %11.4f".format(hi)""")
126132
pr( """ }""")
127133
pr( """ println(sb.result)""")
128134
pr( """ }""")
129135
allops.foreach{ case (o, t, fs) =>
130136
names.foreach{ n =>
131-
pr( s" { // Scope for operations $o collection $n")
132-
pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" )
137+
pr( s" { // Scope for operations $o collection $n")
138+
pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" )
133139
parsefs(fs).foreach{ case (f, pf, ord) =>
134140
if (ordname(n) || !ord) {
135141
if (nojname(n)) {
136-
pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)");
137-
pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)")
142+
pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n${q})");
143+
pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n${q})")
138144
}
139145
if (sqnname(n)) {
140-
pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)")
146+
pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n${q})")
141147
if (nojname(n))
142-
pr( s" timings(x, i => $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)")
148+
pr( s" timings(x, i => $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n${q})")
143149
}
144150
if (parname(n) && pf.isDefined) {
145-
pr( s" timings(x, i => $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)")
151+
pr( s" timings(x, i => $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n${q})")
146152
if (nojname(n))
147-
pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)")
153+
pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n${q})")
148154
}
149-
pr( s" }")
150155
}
151156
}
157+
pr( s" x = null // Allow GC" )
152158
pr( s" } // End scope for operations $o collection $n")
153159
}
154160
}
@@ -159,4 +165,51 @@ object Generator {
159165
case _ =>
160166
}
161167
}
168+
169+
def jmhBench(target: java.io.File = new java.io.File("JmhBench.scala"), sizes: Option[Array[Int]] = Some(jmhsizes)) {
170+
val q = "\""
171+
if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath)
172+
writeTo(target){ pr =>
173+
pr( """// This file auto-generated by bench.codegen.Generator.jmhBench. Do not modify directly.""")
174+
pr( """""")
175+
pr( """package bench.test""")
176+
pr( """""")
177+
pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""")
178+
pr( """import scala.compat.java8.StreamConverters._""")
179+
pr( """import org.openjdk.jmh.annotations._""")
180+
pr( """""")
181+
pr( """@State(Scope.Benchmark)""")
182+
pr( """class JmhBench {""")
183+
pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})")
184+
val m = sizes.map(_.length).getOrElse(new bench.generate.Things().N)
185+
allops.foreach{ case (o, t, fs) =>
186+
names.foreach{ n =>
187+
parsefs(fs).foreach{ case (f, pf, ord) =>
188+
for (i <- 0 until m) {
189+
if (ordname(n) || !ord) {
190+
if (nojname(n)) {
191+
pr( s" @Benchmark def bench_c${t}_${f}_${n}_$i() = $o.$f(x.$n.c$t($i))");
192+
pr( s" @Benchmark def bench_i${t}_${f}_${n}_$i() = $o.$f(x.$n.i$t($i))")
193+
}
194+
if (sqnname(n)) {
195+
pr( s" @Benchmark def bench_ss${t}_${f}_${n}_$i() = $o.$f(x.$n.ss$t($i))")
196+
//if (nojname(n))
197+
// pr( s" @Benchmark def bench_zs${t}_${f}_${n}_$i() = $o.$f(x.$n.zs$t($i))")
198+
}
199+
if (parname(n) && pf.isDefined) {
200+
pr( s" @Benchmark def bench_sp${t}_${f}_${n}_$i() = $o.$f(x.$n.sp$t($i))")
201+
//if (nojname(n))
202+
// pr( s" @Benchmark def bench_zp${t}_${f}_${n}_$i() = $o.$f(x.$n.zp$t($i))")
203+
}
204+
}
205+
}
206+
}
207+
}
208+
}
209+
pr( """}""")
210+
} match {
211+
case Left(t) => println("Did not successfully write file: " + target.getPath); throw t
212+
case _ =>
213+
}
214+
}
162215
}

0 commit comments

Comments
 (0)