I love the power of Scala's for comprehensions and the way they integrate with any monadic type with map and flatMap. However, I'd also like to do simple integer loops without a major speed penalty. Why doesn't Scala have the following two logically identical loops run with similar runtime performance or even compile into similar byte code?
// This is slow...
for (i <- 0 until n) println(s"for loop with $i")
// This runs much faster. It runs roughly at the same speed as Java code doing an identical while or for loop.
var i = 0;
while (i < n) {
println(s"while loop with $i")
i += 1
}
The main (but not only) reason why they're different is boxing.
In the code:
for (i <- 0 until n) println(s"for loop with $i")
You're passing an anonymous function println(s"for loop with $i")
into the comprehension for (i <- 0 until n)
. It's equivalent to:
(0 until n) foreach (i =>
println(s"for loop with $i")
}
That function is erased in the bytecode, which means that i
can't be a primitive int
, it has to be boxed as an Integer
instead. Java doesn't have Fixnum references to avoid this cost in the same way that e.g. Smalltalk does (especially frustrating, given how much older smalltalk is!)
Using -optimize
can help in some cases, especially in trunk builds of scalac.
You can also use scalaxy/loops to speed things up :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With