What would you say is the difference between rev and eventmachine?
Thoughts? (Obviously I can see that both work with 1.9, rev only with
1.9).
On Fri, Feb 15, 2008 at 3:49 PM, Roger P. [email protected]
wrote:
What would you say is the difference between rev and eventmachine?
Thoughts? (Obviously I can see that both work with 1.9, rev only with
1.9).
Rev’s main design goal was to minimize C and build upon Ruby’s existing
socket APIs and OpenSSL bindings. A lot of the features that allow Rev
to
be predominantly Ruby showed up in 1.9, namely the *_nonblock versions
of
various Socket methods. For this reason, a lot of C code was needed to
implement these features in Ruby 1.8 (which is how EventMachine solved
the
problem), but is no longer necessary in Ruby 1.9.
In Rev. there’s two kinds of things: event loops (Rev::Loop) and
Watchers
(event observers), which are all derived from the abstract base class
Rev::Watcher. Subclasses of Rev::Watcher translate incoming events to
higher and higher levels of abstraction. The code is factored into lots
of
small classes that wrap up common behavior in an inheritence hierarchy,
for
example Rev::Sockets and Files are subclassed from Rev::IO, and
Rev::TCPSocket and Rev::UNIXSocket are subclassed from Rev::Socket. I’m
sure this is how EventMachine’s C++ code is factored internally, but
from
the Ruby perspective much of the functionality appears in the flat
EventMachine namespace, which is a Module that exposes singleton methods
like EM.start_tcp_server, EM.start_unix_server, etc instead of using
objects/inheritance.
Being object oriented makes Rev’s API a lot more Ruby-like, and having
as
much code as possible in Ruby means it’s easier for people to hack on it
since they don’t have to know C++. The only things that are C in Rev
are
the libev bindings (which let you monitor Ruby IO objects for
readability/writability, and provide timers), a class for doing
high-speed
buffered network I/O, and a subclass of OpenSSL::SSL::SSLSocket which
adds
nonblocking I/O support. Everything else is written in Ruby.
Building on libev means that the codebase for doing portable,
high-performance cross-platform event monitoring has already undergone a
lot
of debugging and performance tuning. There’s been a lot of problems
with
the EventMachine bindings to epoll, and any improvements to that code
will
only come from people interested in EventMachine specifically (who know
C/C++). libev is in use by a number of people, most notably Rubinius.
libev was also written by a performance-obsessed C guru and benchmarks
quite
nicely, outperforming libevent.
Unfortunately, I haven’t done benchmarks of Rev vs. EventMachine. Maybe
I’ll do some when there’s an official EventMachine release with Ruby
1.9support. If Rev does outperform EventMachine on Ruby
1.9, it might be interesting to do what libev did for libevent:
monkeypatch
some core files of the pure Ruby implementation of EventMachine to use
Rev
as their underlying implementation. EventMachine packs support for a
lot of
features Rev does not, and is used by many, many projects (including
some of
my own) whereas Rev hasn’t seen much use yet.
My main motivation for writing Rev was a feature sorely lacking from
EventMachine which was crucial to implementing Revactor: stoppable /
restartable event monitors.
Every subclass of Rev::Watcher supports the following methods:
attach(loop) - monitor this watcher using the given event loop
disable - temporarily disable event reception
enable - re-enable event reception
detach - remove this watcher from the event loop (for when you’re done
with
a watcher, e.g. when the connection closes, although it’s automatic in
that
case)
Many features of the Actor API in Revactor depend on being able to
temporarily disable event monitoring. Revactor translates events into
messages which get sent to Actor’s mailboxes, so it’s important those
messages are only sent when an Actor is expecting them. This means
any
event source wrapped by the Actor API must be stoppable/restartable, and
in
Rev, these features are implemented in the Rev::Watcher base class, so
they’re available in every subclass.
On Feb 15, 2008, at 6:06 PM, Tony A. wrote:
A lot of the features that allow Rev to
be predominantly Ruby showed up in 1.9, namely the *_nonblock
versions of
various Socket methods.
Is that true? I thought they were added to the 1.8 branch too.
James Edward G. II
readability/writability, and provide timers), a class for doing
high-speed buffered network I/O
Can it buffer incoming I/O?
, and a subclass of OpenSSL::SSL::SSLSocket which
adds
nonblocking I/O support. Everything else is written in Ruby.
Nice
as their underlying implementation. EventMachine packs support for a
lot of
features Rev does not, and is used by many, many projects (including
some of
my own) whereas Rev hasn’t seen much use yet.
Which features?
Thanks!
On Fri, Feb 15, 2008 at 5:13 PM, James G. [email protected]
wrote:
Is that true? I thought they were added to the 1.8 branch too.
Interesting. I wasn’t aware of that, but you appear to be correct.
That
would make adding 1.8 support to Rev a lot easier.
Well, in addition to the *_nonblock methods, the Rev C extension is
using
the rb_thread_blocking_region() function to perform blocking system
calls.
In order to work on 1.8 this would need to be removed and replaced with
a
workaround that blocks only for short intervals then allows the Ruby
scheduler to run.
There’s some other bits which are 1.9 specific which would require
workarounds as well. For example, #instance_exec is used to implement
the
ability to define callbacks at runtime, e.g.:
HOST = ‘127.0.0.1’
PORT = 4321
server = Rev::TCPServer.new(ADDR, PORT) do |c|
c.on_connect { puts “#{remote_addr}:#{remote_port} connected” }
c.on_close { puts “#{remote_addr}:#{remote_port} disconnected” }
c.on_read { |data| write data }
end
server.attach(Rev::Loop.default)
puts “Echo server listening on #{HOST}:#{PORT}”
Rev::Loop.default.run
The on_connect, on_close, and on_read callbacks all use instance_exec to
allow them to execute in the scope of the watcher object (giving access
to
remote_addr, remote_port, write, etc.)
Obviously #instance_eval would suffice for on_connect / on_close, but
on_read takes a parameter, as do several other callbacks in the API.
On Fri, Feb 15, 2008 at 5:42 PM, Roger P. [email protected]
wrote:
Can it buffer incoming I/O?
The actual C buffering code has support for buffering incoming I/O with
Rev::Buffer#read_from(io). However, Rev just dispatches any incoming
data
it reads as it’s read through the on_read callback.
However, read buffering is performed by Revactor, which provides an
imperative, blocking read API, which works just like IO#read
Which features?
Off the top of my head, EventMachine has many protocol adapters
including
SMTP and a (separately bundled) evented HTTP server with an associated
REST
framework, not to mention Evented Mongrel and Thin. It also implements
the
Deferrable pattern for performing blocking calls alongside the event
loop.
I’m sure there’s many more things I’m omitting here.
Rev bundles an asynchronous DNS client which it uses internally for all
DNS
resolution, as well as an HTTP client. Right now there are no HTTP
server
bindings for it.
Revactor allows you to run Mongrel on top of Rev using Actors for
concurrency.
On Feb 15, 2008, at 6:28 PM, Tony A. wrote:
On Fri, Feb 15, 2008 at 5:13 PM, James G.
[email protected]
wrote:Is that true? I thought they were added to the 1.8 branch too.
Interesting. I wasn’t aware of that, but you appear to be correct.
That
would make adding 1.8 support to Rev a lot easier.
Yes, I’m pretty sure EventMachine added a pure Ruby branch after they
were added.
James Edward G. II
Unfortunately, I haven’t done benchmarks of Rev vs. EventMachine. Maybe
I’ll do some when there’s an official EventMachine release with Ruby
1.9support. If Rev does outperform EventMachine on Ruby
1.9, it might be interesting to do what libev did for libevent:
monkeypatch
some core files of the pure Ruby implementation of EventMachine to use
Rev
as their underlying implementation. EventMachine packs support for a
lot of
features Rev does not, and is used by many, many projects (including
some of
my own) whereas Rev hasn’t seen much use yet.
Looks like EM supports 1.9. Might want to try them both out speed-wise
sometime
-R
EM has…
Evented Mongrel and Thin. It also implements
It might well be noted that evented mongrel is something like a 1K patch
to normal mongrel, so not too much And, as you suggested, it would
be interesting to use Rev as the driver for EM (drop in replacement) and
see if it worked.
Cheers!
-Roger
On Wed, Jun 11, 2008 at 3:57 PM, Roger P. [email protected]
wrote:
Looks like EM supports 1.9. Might want to try them both out speed-wise
sometime
Let me say right off the bat that Rev is much slower than EventMachine
on
Ruby 1.8. Rev used to be faster on Ruby 1.9, but EventMachine has since
gotten support for making blocking system calls on Ruby 1.9 and is, in
all
likelyhood, probably faster on 1.9 as well.