From 4cfc633fc6cb2ab0f473c2e5141724017d444dc6 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 12 Dec 2011 06:40:18 -0800 Subject: Range.foreach optimization. This makes code like 0 to 100 foreach (x += _) as fast as (often faster than, in fact) a while loop. See the comment in Range for the gory details. More investigation should be done regarding total impact on inlining behavior. Review by @odersky. --- .../scala/collection/immutable/range-bench.scala | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 test/benchmarks/src/scala/collection/immutable/range-bench.scala (limited to 'test/benchmarks') diff --git a/test/benchmarks/src/scala/collection/immutable/range-bench.scala b/test/benchmarks/src/scala/collection/immutable/range-bench.scala new file mode 100644 index 0000000000..e167ff04e8 --- /dev/null +++ b/test/benchmarks/src/scala/collection/immutable/range-bench.scala @@ -0,0 +1,61 @@ +package scala.collection.immutable +package benchmarks + +object RangeTest { + // not inlined any more, needs investigation + // + // class XXS { + // private val array = Array.range(0, 100) + // def tst = { var sum = 0; for (i <- 0 until array.length) sum += array(i); sum } + // } + + var x: Int = 0 + + def foreachSum(max: Int): Int = { + var sum = 0 + 1 to max foreach (sum += _) + sum + } + def whileSum(max: Int) = { + var sum = 0 + var num = 1 + while (num <= max) { + sum += num + num += 1 + } + sum + } + + def show(max: Int, foreachNanos: Long, whileNanos: Long) { + val winner = if (foreachNanos < whileNanos) "foreachSum" else "whileSum" + val ratio = if (foreachNanos < whileNanos) foreachNanos.toDouble / whileNanos else whileNanos.toDouble / foreachNanos + println("1 to %d:, %12s wins, %.3f: foreach %.3f while %.3f".format( + max, winner, ratio, + foreachNanos.toDouble / 1000000L, + whileNanos.toDouble / 1000000L) + ) + } + + def run(max: Int) = { + val foreachFirst = util.Random.nextBoolean + val t1 = System.nanoTime + x = if (foreachFirst) foreachSum(max) else whileSum(max) + val t2 = System.nanoTime + x = if (foreachFirst) whileSum(max) else foreachSum(max) + val t3 = System.nanoTime + + val foreachNanos = if (foreachFirst) t2 - t1 else t3 - t2 + val whileNanos = if (foreachFirst) t3 - t2 else t2 - t1 + show(max, foreachNanos, whileNanos) + } + + def main(args: Array[String]): Unit = { + var max = if (args.isEmpty) 100 else args(0).toInt + while (max > 0) { + run(max) + run(max) + run(max) + max += (max / 7) + } + } +} -- cgit v1.2.3