This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Lazy vals in a concurrent setting

1 reply
Johannes Rudolph 2
Joined: 2010-02-12,
User offline. Last seen 42 years 45 weeks ago.

Hi,

we recently were reminded that accessing lazy vals locks on the object
holding the lazy vals. This makes using lazy vals in a concurrent
setting awkward if calculating a value is an expensive operation and
thus the lock may be hold for a long time. It is especially expensive
if each (initializing) access to an easily calculated lazy val in the
same object is then obstructed by a long-hold lock for calculating
another lazy val. This would lead to a rule to use lazy vals only if
needed for performance reasons for long-running calculations but not
for smaller calculations. This, however isn't possible because lazy
vals are commonly needed to get around the initialization order
issues.

So, lazy vals, while idiomatic, are an obstacle to parallelization
[1]. This is a pity because in the common cake pattern you will likely
compose several unrelated traits which may contain lazy vals which now
can't be initialized in parallel which in turn slows down the
initialization of applications built with the cake pattern for their
central object. In an application of a certain size debugging these
problem is no fun because the central object will be called from
everywhere and to properly parallelize you have to repeatedly start up
your program to find all accesses to lazy vals in the call path (or
use a profiler).

One workaround I see right now is to manually touch the cheap
lazy-vals to be used concurrently up front to be sure their
calculation won't run into a lock. The other one is to use a special
LazyVal class like I used to do in Java and lock on it for the
long-running calculations. Both workarounds aren't nearly as usable as
the built-in keyword.

Are there any other strategies?

This may seem like a special case but IMO this will become more of a
trap in the future if more software has to run concurrently.
Therefore, lazy vals should be improved to have a lock per lazy val in
the default case. A final solution to this problem would have to
balance memory use (the per-lazy-val lock has to be saved somewhere)
while still maintaining ease of use. David MacIver once conceived of a
way to do so:

http://scala-programming-language.1934581.n4.nabble.com/Question-on-lazy...

Johannes Rudolph 2
Joined: 2010-02-12,
User offline. Last seen 42 years 45 weeks ago.
Re: Lazy vals in a concurrent setting

I created a ticket to keep track of this:

https://issues.scala-lang.org/browse/SI-4798

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland