Scala: for a/vs while {update}

As I mentioned in a post about the performance of Scala’s functional style for expressions compared to the imperative while, the Scala 2.7.0 release is going to improve that over the 2.6.x releases, because they fixed a performance blooper with the Range class. The same code in Scala 2.7.0 RC1 (Release Candidate) makes the for expression over a range about 2.5 times faster. But it’s still 60 times slower than while. I’ll re-post the code and the new comparison results, along with the Time singleton.

object Time {
def apply[T](name: String)(block: => T) {
val start = System.currentTimeMillis
try {
block
} finally {
val diff = System.currentTimeMillis – start
println(“# Block \”” + name +”\” completed, time taken: ” + diff + ” ms (” + diff / 1000.0 + ” s)”)
}
}
}

object ComprehensionPerfImpact {
def main(args : Array[String]) : Unit = {
val n = 100000000

Time(“for-comprehension”) {
for (x < - 1 to n) {} } Time("while") { var x = 0 while (x <= n) { x += 1 } } } }[/sourcecode] # Block “for-comprehension” completed, time taken: 6672 ms (6.672 s)
# Block “while” completed, time taken: 109 ms (0.109 s)

The previous results with Scala 2.6.0 were: 16.797 s vs. 0.125 s. Note that the small difference in while performance between then and now is probably random, as the results differ a bit on each execution.

In the previous post the conclusion was that since a while expression is compiled into some simple byte-code that uses goto, and for is translated into some higher-order function calls, they can never quite match in performance. But this still seems like an awfully big difference to me. If I find some time for it during this week or the next, I’ll profile the code in detail and find what exactly causes the for-comprehension to perform so slowly.

Continue reading

Scala: for a/vs while

After posting about the (almost non-existent) performance impact of implicit conversions, I noticed something that blew my mind somewhat: if I used a for expression instead of while, the code ran much longer. How much? About a hundred times. Here’s a simple example, and again it’s such an example that brings out the difference between two “primitive” things taken out of context, so it doesn’t really tell us anything about real-life application performance:

object ComprehensionPerfImpact {
def main(args : Array[String]) : Unit = {
val n = 100000000

Time(“for-comprehension”) {
for (x < - 1 to n) {} } Time("while") { var x = 0 while (x <= n) { x += 1 } } } }[/sourcecode] The output:# Block “for-comprehension” completed, time taken: 16797 ms (16.797 s)
# Block “while” completed, time taken: 125 ms (0.125 s)

Update: I forgot to mention that this test was made with Scala version 2.6.0. I have also now run this on Scala 2.7.0 RC1, where the results are about 2.5 times faster.

Continue reading

Learning Scala: Performance Impact of Implicit Conversions

Scala’s implicit conversions are a great tool for enhancing classes coming from libraries that you can’t just change yourself. I went into details on how it works a few weeks ago. With implicit conversions it can be made to appear that methods you have written exist as part of some objects that actually remain unchanged. You usually do this by creating (1) a wrapper class that takes the original object as it’s single parameter and (2) an implicit function that converts the original to the wrapped type by instantiating and returning the wrapper. If such an implicit is in a given scope, then in that scope the wrapper type’s methods can be called as if they were part of the wrapped class. For example, see the code below (note: the syntax highlighting is not perfect because it’s using Java rules — if anyone knows an easy way to add Scala highlighting support to a wordpress.com blog, please let me know in the comments):

case class ImmutableRichLong(x: Long) {
  // returns the predecessor of the wrapped object
  def pred = x - 1
}

implicit def long2immutableRichLong(x: Long) = ImmutableRichLong(x)

20L.pred // returns 19

Other languages have ways of doing similar things. JavaScript and Ruby actually let you add methods to existing objects, and these methods will then work everywhere else where those objects are used, which is not always good. A badly behaving piece of code could easily screw things up for everyone that way. Extension methods in C# are more similar to Scala’s implicit conversion, but they don’t require actual creation of new objects — they are just a mechanism for invoking static methods as if they were members of their first parameter. I’m not sure what to think about that. I guess it might be preferable to just calling the method normally, in some DSL scenario. Continue reading