Skip to content

Commit 00977b8

Browse files
committed
Added overlooked Operations file!
Also wrote a first pass of a Thyme benchmark generator.
1 parent 29b5ad1 commit 00977b8

File tree

2 files changed

+215
-31
lines changed

2 files changed

+215
-31
lines changed

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

Lines changed: 98 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,53 +40,120 @@ object Generator {
4040
val q = "\""
4141
if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath)
4242
writeTo(target){ pr =>
43-
pr( """package bench.test""")
44-
pr( """""")
45-
pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""")
46-
pr( """import scala.compat.java8.StreamConverters._""")
47-
pr( """""")
48-
pr( """object Agreement {""")
49-
pr( """ def run() {""")
50-
pr( """ val wrong = new collection.mutable.ArrayBuffer[String]""")
51-
pr( """ def check[A](a1: A, a2: => A, msg: String) {""")
52-
pr( """ var t = System.nanoTime""")
53-
pr( """ if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""")
54-
pr( """ wrong += msg""")
55-
pr( """ if (t > 2000000000) wrong += "Slow " + msg""")
56-
pr( """ }""")
57-
pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" )
43+
pr( """package bench.test""")
44+
pr( """""")
45+
pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""")
46+
pr( """import scala.compat.java8.StreamConverters._""")
47+
pr( """""")
48+
pr( """object Agreement {""")
49+
pr( """ def run() {""")
50+
pr( """ val wrong = new collection.mutable.ArrayBuffer[String]""")
51+
pr( """ def check[A](a1: A, a2: => A, msg: String) {""")
52+
pr( """ var t = System.nanoTime""")
53+
pr( """ if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""")
54+
pr( """ wrong += msg""")
55+
pr( """ if (t > 2000000000) wrong += "Slow " + msg""")
56+
pr( """ }""")
57+
pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" )
5858
allops.foreach{ case (o, t, fs) =>
5959
names.foreach{ n =>
60-
pr( s" { // Scope for operations $o collection $n")
61-
pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" )
60+
pr( s" { // Scope for operations $o collection $n")
61+
pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" )
6262
parsefs(fs).foreach{ case (f, pf, ord) =>
6363
if (ordname(n) || !ord) {
64-
pr( """ for (i <- 0 until m) {""")
65-
pr( s" val z = $o.$f(x.arr.c$t(i))")
64+
pr( """ for (i <- 0 until m) {""")
65+
pr( s" val z = $o.$f(x.arr.c$t(i))")
6666
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)")
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)")
6969
}
7070
if (sqnname(n)) {
71-
pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)")
71+
pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)")
7272
if (nojname(n))
73-
pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)")
73+
pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)")
7474
}
7575
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)")
76+
pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)")
7777
if (nojname(n))
78-
pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)")
78+
pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)")
7979
}
80-
pr( s" }")
80+
pr( s" }")
8181
}
8282
}
83-
pr( s" } // End scope for operations $o collection $n")
83+
pr( s" } // End scope for operations $o collection $n")
8484
}
8585
}
86-
pr( """ wrong.foreach(println)""")
87-
pr( """ if (wrong.nonEmpty) sys.exit(1) """)
88-
pr( """ }""")
89-
pr( """}""")
86+
pr( """ wrong.foreach(println)""")
87+
pr( """ if (wrong.nonEmpty) sys.exit(1) """)
88+
pr( """ }""")
89+
pr( """}""")
90+
} match {
91+
case Left(t) => println("Did not successfully write file: " + target.getPath); throw t
92+
case _ =>
93+
}
94+
}
95+
96+
def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]]) {
97+
val q = "\""
98+
if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath)
99+
writeTo(target){ pr =>
100+
pr( """package bench.test""")
101+
pr( """""")
102+
pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""")
103+
pr( """import scala.compat.java8.StreamConverters._""")
104+
pr( """import ichi.bench.Thyme""")
105+
pr( """""")
106+
pr( """object Agreement {""")
107+
pr( """ def run() {""")
108+
pr( """ val th = Thyme.warmed()""")
109+
pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" )
110+
pr( """ def timings[A](x: bench.generate.Things, op: Int => A, name: String) {""")
111+
pr( """ val ts = new collection.mutable.ArrayBuffer[(Double, Double, Double)]""")
112+
pr( """ for (i <- 0 until m) {""")
113+
pr( """ val b = Thyme.Benched.empty""")
114+
pr( """ val a = th.bench(op(i))(b)""")
115+
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)""")
117+
pr( """ }""")
118+
pr( """ val sb = new StringBuilder""")
119+
pr( """ sb ++= name + $q: $q""")
120+
pr( """ if (sb.length < 36) sb ++= $q $q * (36 - sb.length)""")
121+
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)""")
126+
pr( """ }""")
127+
pr( """ println(sb.result)""")
128+
pr( """ }""")
129+
allops.foreach{ case (o, t, fs) =>
130+
names.foreach{ n =>
131+
pr( s" { // Scope for operations $o collection $n")
132+
pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" )
133+
parsefs(fs).foreach{ case (f, pf, ord) =>
134+
if (ordname(n) || !ord) {
135+
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)")
138+
}
139+
if (sqnname(n)) {
140+
pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)")
141+
if (nojname(n))
142+
pr( s" timings(x, i => $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)")
143+
}
144+
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)")
146+
if (nojname(n))
147+
pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)")
148+
}
149+
pr( s" }")
150+
}
151+
}
152+
pr( s" } // End scope for operations $o collection $n")
153+
}
154+
}
155+
pr( """ }""")
156+
pr( """}""")
90157
} match {
91158
case Left(t) => println("Did not successfully write file: " + target.getPath); throw t
92159
case _ =>
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package bench.operate
2+
3+
import java.util.stream._
4+
import java.util.{function => jf}
5+
import scala.compat.java8.StreamConverters._
6+
import scala.compat.java8.converterImpl._
7+
import scala.compat.java8.collectionImpl._
8+
9+
object CloseEnough {
10+
import scala.math._
11+
def apply[A](a: A, b: => A): Boolean = a match {
12+
case da: Double => b match {
13+
case db: Double => (da.isNaN && db.isNaN) || abs(da - db) <= max(1, max(abs(da), abs(db)))*1e-6
14+
case x => a == x
15+
}
16+
case _ => a == b
17+
}
18+
}
19+
20+
object OnInt {
21+
def expensive(i: Int) = { var v = i.toDouble; var j = 0; while (j < 10) { v = math.exp(math.sin(v)); j += 1 }; v+j }
22+
23+
def sum(a: Array[Int]): Int = { var s,i = 0; while (i < a.length) { s += a(i); i += 1 }; s }
24+
def sum(t: Traversable[Int]): Int = t.sum
25+
def sum(i: Iterator[Int]): Int = i.sum
26+
def sum(s: IntStepper): Int = s.fold(0)(_ + _)
27+
def sum(s: IntStream): Int = s.sum
28+
def psum(i: Iterable[Int]): Int = i.par.sum
29+
def psum(s: IntStream): Int = s.parallel.sum
30+
31+
def trig(a: Array[Int]): Double = { var i = 0; var s = 0.0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s }
32+
def trig(t: Traversable[Int]): Double = t.map(expensive).sum
33+
def trig(i: Iterator[Int]): Double = i.map(expensive).sum
34+
def trig(s: IntStepper): Double = s.fold(0.0)((x,i) => x + expensive(i))
35+
def trig(s: IntStream): Double = s.mapToDouble(new jf.IntToDoubleFunction{ def applyAsDouble(i: Int) = expensive(i) }).sum
36+
def ptrig(i: Iterable[Int]): Double = i.par.map(expensive).sum
37+
def ptrig(s: IntStream): Double = trig(s.parallel)
38+
39+
def fmc(a: Array[Int]): Int = { var s,i = 0; while (i < a.length) { if (i%7 == 1) s += (i/7)*i; i += 1 }; s }
40+
def fmc(t: Traversable[Int]): Int = t.filter(x => (x%7) == 1).map(x => (x/7)*x).sum
41+
def fmc(i: Iterator[Int]): Int = i.filter(x => (x%7) == 1).map(x => (x/7)*x).sum
42+
def fmc(s: IntStream): Int = s.
43+
filter(new jf.IntPredicate { def test(x: Int) = (x%7) == 1 }).
44+
map(new jf.IntUnaryOperator{ def applyAsInt(x: Int) = (x/7)*x }).
45+
sum
46+
def pfmc(i: Iterable[Int]): Int = i.par.filter(x => (x%7) == 1).map(x => (x/7)*x).sum
47+
def pfmc(s: IntStream): Int = fmc(s.parallel)
48+
49+
def mdtc(a: Array[Int]): Int = { var i = 1; while(i < a.length) { if ((a(i) << 1) >= 42) return i-1; i += 1 }; i - 1 }
50+
def mdtc(t: Traversable[Int]): Int = t.map(_ << 1).drop(1).takeWhile(_ < 42).size
51+
def mdtc(i: Iterator[Int]): Int = i.map(_ << 1).drop(1).takeWhile(_ < 42).size
52+
def mdtc(s: IntStream): Int = {
53+
val temp = s.map(new jf.IntUnaryOperator { def applyAsInt(x: Int) = x << 1 }).skip(1)
54+
val acc = new IntAccumulator
55+
temp.allMatch(new jf.IntPredicate{ def test(x: Int) = if (x < 42) { acc += x; true } else false })
56+
acc.size.toInt
57+
}
58+
}
59+
60+
object OnString {
61+
def expensive(s: String) = { val h = scala.util.hashing.MurmurHash3.stringHash(s); OnInt.expensive(h) }
62+
63+
def nbr(a: Array[String]): Int = { var s,i = 0; while (i < a.length) { if (a(i).charAt(a(i).length-1) < '5') s += 1; i += 1 }; s }
64+
def nbr(t: Traversable[String]): Int = t.count(s => s.charAt(s.length-1) < '5')
65+
def nbr(i: Iterator[String]): Int = i.count(s => s.charAt(s.length-1) < '5')
66+
def nbr(p: Stepper[String]): Int = p.fold(0)((i,s) => if (s.charAt(s.length-1) < '5') i+1 else i)
67+
def nbr(q: Stream[String]): Int = q.filter(new jf.Predicate[String] { def test(s: String) = s.charAt(s.length-1) < '5' }).count.toInt
68+
def pnbr(i: Iterable[String]): Int = i.par.count(s => s.charAt(s.length-1) < '5')
69+
def pnbr(q: Stream[String]): Int = nbr(q.parallel)
70+
71+
def htrg(a: Array[String]): Double = { var s = 0.0; var i = 0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s }
72+
def htrg(t: Traversable[String]): Double = t.map(expensive).sum
73+
def htrg(i: Iterator[String]): Double = i.map(expensive).sum
74+
def htrg(p: Stepper[String]): Double = p.fold(0.0)((x,s) => x + expensive(s))
75+
def htrg(q: Stream[String]): Double = q.mapToDouble(new jf.ToDoubleFunction[String]{ def applyAsDouble(s: String) = expensive(s) }).sum
76+
def phtrg(i: Iterable[String]): Double = i.par.map(expensive).sum
77+
def phtrg(q: Stream[String]): Double = htrg(q.parallel)
78+
79+
def fmc(a: Array[String]): Int = {
80+
var s, i = 0
81+
while (i < a.length) {
82+
val x = a(i)
83+
if (x.charAt(x.length-1) == '1' && (x.length > 2 || (x.charAt(0) != '-' && x.length > 1))) s += 1
84+
i += 1
85+
}
86+
s
87+
}
88+
def fmc(t: Traversable[String]): Int =
89+
t.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1)
90+
def fmc(i: Iterator[String]): Int =
91+
i.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1)
92+
def fmc(q: Stream[String]): Int =
93+
q.filter(new jf.Predicate[String]{ def test(x: String) = x.charAt(x.length-1) == '1' }).
94+
map[String](new jf.Function[String, String]{ def apply(x: String) = if (x.charAt(0) == '-') x.substring(1) else x }).
95+
filter(new jf.Predicate[String]{ def test(x: String) = x.length > 1 }).
96+
count.toInt
97+
def pfmc(i: Iterable[String]): Int =
98+
i.par.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1)
99+
def pfmc(q: Stream[String]): Int = fmc(q.parallel)
100+
101+
def mdtc(a: Array[String]): Int = {
102+
var i = 1
103+
while (i < a.length) {
104+
if (a(i).reverse.length >= 3) return i-1
105+
i += 1
106+
}
107+
i-1
108+
}
109+
def mdtc(t: Traversable[String]): Int = t.map(_.reverse).drop(1).takeWhile(_.length < 3).size
110+
def mdtc(i: Iterator[String]): Int = i.map(_.reverse).drop(1).takeWhile(_.length < 3).size
111+
def mdtc(q: Stream[String]): Int = {
112+
val temp = q.map[String](new jf.UnaryOperator[String] { def apply(x: String) = x.reverse }).skip(1)
113+
val acc = new Accumulator[String]
114+
temp.allMatch(new jf.Predicate[String]{ def test(x: String) = if (x.length < 3) { acc += x; true } else false })
115+
acc.size.toInt
116+
}
117+
}

0 commit comments

Comments
 (0)