Alex Payne writes online here.

See also the archive, books & talks.

An individual post follows.

C4 Day Two: Steve Dekorte on scaling with actors

I was hosting my notes for collaborative editing via SubEthaEdit during the conference, but about halfway through Steve Dekorte’s talk the application crashed. This was no great loss, as others had been sharing equally thorough notes, and Steve was kind enough to post his talk.

It probably bears mention that I’m as big a fan of Steve Dekorte and his projects as one can be of someone you only know through his web presence. His blog is one of my favorite daily reads and his programming language, Io, is an absolute joy. His talk was really the clincher when deciding whether or not to attend C4 and I was on the edge of my seat for it despite the day wearing on.

Dekorte has a stage manner as modest and direct as his writing and design aesthetic, which was the perfect compliment to his challenging topic of coping with multi-core processors, all too important given rumors of eight core Macs in the near future. Clock speed, we were told, is leveling off, and adding cores is the chip makers’ solution to ever-increasing performance demands. Beyond these chips-within-chips, programmers must also contend with scaling their code to make use of clustered computing environments.

The argument against traditional concurrency models is strong: preemptive threads are nondeterministic – what he called “spaghetti concurrency,” illustrated with a telling graph – and shared memory. This makes a guessing game out of writing concurrent software, as lock coordination is left up to the programmer to mangle. This doesn’t even begin to take into account the problems of scaling across clusters and remote services. Threads are dead in the water.

Dekorte believes that the Actor model is the superior abstraction for writing complex multitasking applications. An actor is an object with its own asynchronous message queue and an execution context for processing that queue. State, instructions, and execution are all encapsulated in the Actor model, which Dekorte believes to be a “natural extension of the object paradigm.” Whereas traditional concurrency models allow threads to modify each other’s state, the actor model states that a thread can only modify its own state. The message queue associated with an actor is thus a FIFO queue of requests to change state.

As a playground for this and other ideas, Dekorte has developed the aforementioned Io programming language. Io was used for all examples as we delved into the practical implementation of actors and asynchronous programming. The concept of futures is central to this topic, and was our first stop. Futures are essentially a placeholder object for the result of a pending operation; they become the result when the result is available and block if accessed prematurely. This decouples messages from return values (the essence of asynchronous programming) and allows for neat tricks like automatic deadlock detection by walking through the tree of actor dependencies and recording blocking operations. A massively parallel HTTP downloading tool was used as an example.

Once a single machine has been maximized through asynchronous programming, the problem of distributed programming remains. While traditional models broker requests or use other languages as proxies (XML-RPC), a more efficient model employs transparent distributed objects to unify local and remote messaging. This simplifies interprocess communication across a network but can still suffer from latency issues. A peer-to-peer service was used as an example.

Further problems remain, but solutions abound. Memory bottlenecks in highly concurrent applications can be mitigated through stackless (frames linked in the heap) coroutines or continuations. Blocking operations can be delegated to asynchronous I/O or managed by pausing user-level threads. As a demonstration of the value of asynchronous techniques Dekorte relied on this graph of the Apache and YAWS web servers and their respective performance over time as the number of sessions increases. YAWS, poster child for the asynchronous capabilities of the Erlang language, trounces Apache under load with its lightweight threading.

Before the Q&A session we were treated to a visualization of Dekorte’s vision of the future of scalable architecture. Our speaker “zoomed out” in a series of slides, starting with small programmatic constructs and ending up with enormous grid systems. It’s a big world for this technology.

After such a thorough talk, the questions were relatively few. We found out that Io recently acquired OS-level threads which should enable it to readily take advantage of multiple cores. When asked why Io doesn’t return futures by default, Dekorte had the simple answer of “performance”; futures cost extra memory (there’s really no escape from deeply understanding your concurrency model, whether traditional or otherwise). An audience member suggested that implementing Conway’s Game of Life would be fun in an actor-based language. And it was suggested that higher-level coordination patterns would be most useful in conjunction with the actor paradigm.

I was totally pleased with Dekorte’s talk. It was dense with information yet eminently comprehensible. My only regret is the lack of time I’ve had since the talk to play with the concepts I learned.