This is a known problem and has been discussed previously here:
http://thread.gmane.org/gmane.comp.lang.scala.internals/865
Separating the hot part of the code into a separate method so that it
can be inlined is also a known technique, but good to emphasize it for
this scenario with examples. Note that even if you use that style
you're not guaranteed to have what you want now. Supposedly JVMs will
be better at doing the right thing in the future.
> Otherwise, it would be good to discuss whether the style he suggests can (or
> should) be implemented in the Scala compiler, and/or whether some
> specialization trick can be brought to bear.
I guess something could be done along the same lines as @specialized,
but seems like a significant amount of work and something best handled
at JVM level, really (I guess one could say the same thing about
@specialized).
Best,
Ismael
The problem is that current jvm heuristics are mostly based on single call sites,
and call-site based optimizations are fundamentally at odds with higher-order
functions: If you have
def foreach(f) = {
val iter = this.iterator
while (iter.hasNext)
f(iter.next) // A
}
foreach { x => // B
...
}
foreach { x => // C
...
}
Then inlining (or building a polymorphic inline cache) at call site A will lead nowhere but
it is quite likely that the jvm will do just that. Even if you inline foreach at B or C
you are in trouble if you add another layer:
def exists(f) = {
foreach { x =>
if (f(x)) return true
}
false
}
Let's say you have custom logic that inlines all foreach calls, then the problem is just
shifted from foreach to exists. Inlining foreach into exists will get the caller of exists
nowhere.
Scalac's -optimize flag and @inline annotations can help in some cases but unfortunately
only for final methods. The problem here is that scalac has to be pessimistic and
it cannot know whether methods will be overridden by classes loaded at runtime
(open world assumption). Of course we want collections to be extensible.
As a final note, this problem has also come up in our work on compiled DSLs. There,
life is much easier for two reasons: first, we can do whole-program optimization and
second, we can use staging to effectively implement foreach, exists, etc as macros
that will always be expanded completely (i.e. the generated code will contain just
the while loops at appropriate places).
- Tiark
Btw. I just found this thread, which might be of interest:
http://groups.google.com/group/jvm-languages/browse_thread/thread/72a5f4b16eba3505
Regards,
Rüdiger
2011/4/6 Alex Cruise <al...@cluonflux.com>:
Regards,
Rüdiger
2011/4/7 Ruediger Keller <ruedige...@rk42.de>:
It would be nice to have whole-program optimization switch for plain
Scala code too. Libraries can't benefit from this, but many of us have
self-contained applications that would.
Since the initial blog post, Remi Forax wrote a prototype that relies
on a Java agent:
Fixing The Inlining “Problem” - A prototype
http://weblogs.java.net/blog/forax/archive/2011/04/08/fixing-inlining-%E2%80%9Cproblem%E2%80%9D-prototype
Best,
Ismael
Yeah.
I know that the early efforts at whole-program optimizations have not
developed into a tool that's in practical use. Was it ever explored
having just *some* of the program being fixed at compile time? For
optimizing the iteration methods on collections, much should be
possible based only on the assumption that the Scala standard library
is known.
Lex