esme-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Pollak <>
Subject New Lift Actor code
Date Sat, 23 May 2009 05:19:28 GMT

It is not lightly that I've made the decision to write an alternative Actor
library and move the Lift code base from the Scala Actors to Lift Actors
(working name).  I want to spend a little time talking about the steps that
led to the decision as well as the impact that it will have on Lift code.

Since November, I've been chasing a series of memory leaks in the Actor
library.  Philipp Haller from EPFL has been responsive in addressing the
individual memory leaks, but the issue seems to be one of whack-a-mole...
each time one memory leak is fixed, another one appears.  Further, the
existing Actor architecture does not lend itself to the kind of Actor usage
cycle that we find in Lift apps.  Specifically:

   - Lift creates/destroys an Actor for each Comet request.  This rapid
   creation/destruction of Actors caused memory back-ups, and the existing
   Actor code seems to be oriented to long running Actors rather than Actors
   with Object-length lifespans.
   - The FJ libraries used for Actor scheduling have problems on multi-core
   machines and are also a source of memory retention issues.
   - Replacing the FJ libraries with a scheduler based on
   java.util.concurrent exposes race/deadlock conditions related to the fact
   that some parts of the Actor processing (e.g., testing mailbox items against
   partial functions while the Actor itself is synchronized)
   - The Actors require external threads to function and it's not possible
   to create external threads in the Google App Engine (making Actor-based
   functionality including CometActors non-functioning in GAE apps)
   - Actors are fragile when exceptions are thrown
   - Actors have running and not running states (as compared with objects
   which can always respond to message sends).  In practice, managing the
   running and not running states is as hard as managing memory in C.
   - There are hidden actors associated with each thread which display the
   above fragility and state management issues
   - And as a practical matter, I've got a couple of applications that are
   going into production over the next few weeks and cannot wait for the
   various fixes to make it into Scala 2.8 and the hacks and work-arounds that
   I've done to the 2.7.4 Actor libraries became too complex for my comfort.

I have written a simple Actor class that is focused on message sending and
processing of messages asynchronously.  This means there's a single
operation that you can perform on Actors, the message send operation.
Actors can be specicialized (they only access messages of a certain type).
In order to receive a response from an Actor, you can pass in a Future as
part of the message and that Future may be satisfied asynchronously.  This
means that a sender of a message need not be an Actor and that the Actor
recipient of a message cannot determine the sender of a message.  Actors
have two bits of internal state: a mailbox and a flag indicating that the
Actor is currently processing messages in its mailbox.  The amount of
synchronization of Actors is minimal (on inserting messages into the
mailbox, on removing messages from the mailbox, and on changing state
to/from "processing messages".)

An Actor instance must provide a messageHandler method which returns a
PartialFunction that is used to pattern match against the messages in the
mailbox.  The instance may also provide an optional exception handler that
is called if an Exception is thrown during the handling of a message.

The Actor is guaranteed to only be processing one message at a time and the
Actor is guaranteed not to be in a monitor (synchronized) during the
processing of messages.  An Actor is guaranteed to maintain the order of the
messages in its mailbox, however, messages that do not currently match the
messageHandler will be retained in the order that they were received in the
event that the messageHandler changes and they can be processed.

The Lift Actors will, by default, use the java.util.concurrent library for
thread pooling, although I have worked out a mechanism for
thread-piggy-backing such that if the Actors are running in GAE, they need
not use any additional thread (this will enable Lift's comet support in
GAE.)  There will also be a scheduler (much like the existing ActorPing)
which will send a message to an Actor at some time in the future (and on
GAE, this scheduler, the Pinger, will not require a separate thread.)

The changes that you will have to make to your applications are minimal.
Actors will no longer have start(), exit(), or link() methods.  Actors will
always process messages in their mailbox and will be removed from the system
by the JVM's garbage collector.  Calls to !? will be replaced by calls to !
with a Future as a parameter to the message.  Calls to ActorPing will be
replaced by calls to Pinger.

You can continue to mix Scala's Actors and Lift's Actors in an application,
although Lift's work-arounds to the Scala Actor memory retention issues and
scheduling issues will not be turned on by default (they will still be
available in the Lift codebase if you're using Scala 2.7.4 and need the

I am happy to share the Lift Actor code with EPFL and if it makes it into
the Scala distribution as SimpleActors or something similar, I'm totally
cool with that.  I'm not interested in owning or maintaining an Actor
library.  I am however, dedicated to making sure that Lift apps can run in
production for months (or even years) without retaining memory or having
other problems that can impact the stability of applications.

I will have a branch committed up on GitHub tomorrow with Lift ported to the
new Actor library.

If you have any questions, please let me know.



PS -- ESME people, I'll roll these changes into ESME next week

Lift, the simply functional web framework
Beginning Scala
Follow me:
Git some:

  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message