On Jan 22, 2008 4:39 PM, [email protected] [email protected] wrote:
I’m still trying to wrap my head around this whole concept. What is
the difference in approach between Revactor and EventMachine ? I
can see that one works with 1.8 and the other starts with 1.9 but they
seem to me, the uneducated reader, very similar. Am I missing
Revactor implements the Actor model and EventMachine implements the
pattern (hmm, Reactor, Revactor, a little confusing I’m sure. My bad).
similarities between Actor and Reactor do go much deeper than their
Both provide ways of programming performant and highly concurrent
The main drawback of Reactor I’ve encountered is that it’s fully
asynchronous and relies on inversion of control. That’s not to say this
a bad thing: it’s great for anything that does event processing,
particularly of incoming messages. However, Actors also support this
of programming. For more information see the Revactor::TCP
The main advantage of Actor over Reactor in this regard involves APIs
require synchronous interfaces and just won’t work without them.
the best example of this I can think of is ActiveRecord. With a simple
Foo.find(:first).bar.baz you’ve traversed across two associations which
made their own query and blocked until they had the results, because the
next method invocation needed it. It’s not the most efficient approach
the world, but it’s there when you need it. Unfortunately, it’s just
possible on top of a Reactor API, but works fine on top of Actors.
Using Reactor means you must abandon any code which is structured around
making synchronous blocking calls to interact with the network. This
includes pretty much everything built on the traditional imperative
API. Everything must use an asynchronous API. There are ways around
such as spinning off any synchronous blocking calls in a separate
but then you need a thread for each blocking call you wish to make, and
there are performance issues with threads and I/O in Ruby, not to
the traditional pitfalls of threaded programming.
With Actors, you can pull in any code that uses the existing Sockets
(monkey)patch in Revactor::TCP::Sockets in their place, and you’re good
go. You can mix and match synchronous and asynchronous programming
ever having to involve threads.
Perhaps the biggest argument for Actors is how many network applications
up being structured internally. Time and time again the optimal
architecture seems to be discrete components which communicate with
passing. For an idea of this, have a look at a digram of qmail:
Qmail is implemented as a number of C programs which communicate using
pipes. Reactor also works well with this approach: implement each
as a process, and have them communicate using pipes, sockets, etc.
The Actor model is built around the idea of discrete components which
communicate using message passing, but gets rid of the headaches
with process invocation, setting up IPC channels, etc. Rather than
heavyweight OS process, each discrete component is a lightweight Ruby
Fiber. This means building systems which rely on independent components
which communicate with message passing is both lightweight and