Skip to content
This repository has been archived by the owner on Feb 23, 2018. It is now read-only.

Foreach Optimization

Paul Phillips edited this page Apr 6, 2011 · 1 revision

Ambition: rework Range into a form where it can be optimized without having to special case the optimizer. (I am not sure this is even possible.)

for (x <- 1 to n)
  parser.f()

It looks like this loop should be pretty easy to optimize (the index variable is never used), but it turns out that, even optimized, it is pretty slow. I don't find the numbers right now, but it was 2-3 slower than an equivalent

n times parser.f()

(where times has the obvious implementation in RichInt).

At least two problems:

  • the Range class is pretty complex, having several subclasses, like Inclusive and Exclusive. Some methods are simply too hard to resolve and inline.
  • analysis in the optimizer may be too simple. For instance, a simple side-effect analysis could help tremendously.

Currently, on the previous example the foreach and the closure are indeed inlined and eliminated, but the Range object itself is not. I think that's because there are many methods that are not inlined, like for instance 'last', 'step', 'start'.

I propose we create a range class written with no purpose in life except making life easy on the optimizer, with the minimum code necessary to do stepped counting. I think we could even take it out of the collections and use an implicit conversion to NumericRange to make it feel the same, although I'm not clear on how much this would help.

I think the Inclusive/Exclusive may be an optimization. Presumably, the JIT will be able to inline/optimize better when the type does not change, while a flag test may not be optimized away. I don't know what is their motivation either, but it may something along this line. The issue is that, while making the program (presumably) faster in the baseline case, it hurts the optimizer. Unfortunately, I don't have any evidence yet, it's just speculation.

Clone this wiki locally