This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
EventMachine (EM) adds two different formalisms for lightweight concurrency to
|
||||
the Ruby programmer's toolbox: spawned processes and deferrables. This note
|
||||
will show you how to use them.
|
||||
|
||||
|
||||
=== What is Lightweight Concurrency?
|
||||
|
||||
We use the term "Lightweight Concurrency" (LC) to refer to concurrency
|
||||
mechanisms that are lighter than Ruby threads. By "lighter," we mean: less
|
||||
resource-intensive in one or more dimensions, usually including memory and
|
||||
CPU usage. In general, you turn to LC in the hope of improving the
|
||||
performance and scalability of your programs.
|
||||
|
||||
In addition to the two EventMachine mechanisms we will discuss here, Ruby
|
||||
has at least one other LC construct: Fibers, which are currently under
|
||||
development in Ruby 1.9.
|
||||
|
||||
The technical feature that makes all of these LC mechanisms different from
|
||||
standard Ruby threads is that they are not scheduled automatically.
|
||||
|
||||
When you create and run Ruby threads, you can assume (within certain
|
||||
constraints) that your threads will all be scheduled fairly by Ruby's runtime.
|
||||
Ruby itself is responsible for giving each of your threads its own share of
|
||||
the total runtime.
|
||||
|
||||
But with LC, your program is responsible for causing different execution
|
||||
paths to run. In effect, your program has to act as a "thread scheduler."
|
||||
Scheduled entities in LC run to completion and are never preempted. The
|
||||
runtime system has far less work to do since it has no need to interrupt
|
||||
threads or to schedule them fairly. This is what makes LC lighter and faster.
|
||||
|
||||
You'll learn exactly how LC scheduling works in practice as we work through
|
||||
specific examples.
|
||||
|
||||
|
||||
=== EventMachine Lightweight Concurrency
|
||||
|
||||
Recall that EM provides a reactor loop that must be running in order for
|
||||
your programs to perform event-driven logic. An EM program typically has a
|
||||
structure like this:
|
||||
|
||||
require 'eventmachine'
|
||||
|
||||
# your initializations
|
||||
|
||||
EM.run {
|
||||
# perform event-driven I/O here, including network clients,
|
||||
# servers, timers, and thread-pool operations.
|
||||
}
|
||||
|
||||
# your cleanup
|
||||
# end of the program
|
||||
|
||||
|
||||
EventMachine#run executes the reactor loop, which causes your code to be
|
||||
called as events of interest to your program occur. The block you pass to
|
||||
EventMachine#run is executed right after the reactor loop starts, and is
|
||||
the right place to start socket acceptors, etc.
|
||||
|
||||
Because the reactor loop runs constantly in an EM program (until it is
|
||||
stopped by a call to EventMachine#stop), it has the ability to schedule
|
||||
blocks of code for asynchronous execution. Unlike a pre-emptive thread
|
||||
scheduler, it's NOT able to interrupt code blocks while they execute. But
|
||||
the scheduling capability it does have is enough to enable lightweight
|
||||
concurrency.
|
||||
|
||||
|
||||
For information on Spawned Processes, see the separate document
|
||||
SPAWNED_PROCESSES.
|
||||
|
||||
For information on Deferrables, see the separate document DEFERRABLES.
|
||||
|
||||
|
||||
=== [SIDEBAR]: I Heard That EventMachine Doesn't Work With Ruby Threads.
|
||||
|
||||
This is incorrect. EM is fully interoperable with all versions of Ruby
|
||||
threads, and has been since its earliest releases.
|
||||
|
||||
It's very true that EM encourages an "evented" (non-threaded) programming
|
||||
style. The specific benefits of event-driven programming are far better
|
||||
performance and scalability for well-written programs, and far easier
|
||||
debugging.
|
||||
|
||||
The benefit of using threads for similar applications is a possibly more
|
||||
intuitive programming model, as well as the fact that threads are already
|
||||
familiar to most programmers. Also, bugs in threaded programs often fail
|
||||
to show up until programs go into production. These factors create the
|
||||
illusion that threaded programs are easier to write.
|
||||
|
||||
However, some operations that occur frequently in professional-caliber
|
||||
applications simply can't be done without threads. (The classic example
|
||||
is making calls to database client-libraries that block on network I/O
|
||||
until they complete.)
|
||||
|
||||
EventMachine not only allows the use of Ruby threads in these cases, but
|
||||
it even provides a built-in thread-pool object to make them easier to
|
||||
work with.
|
||||
|
||||
You may have heard a persistent criticism that evented I/O is fundamentally
|
||||
incompatible with Ruby threads. It is true that some well-publicized attempts
|
||||
to incorporate event-handling libraries into Ruby were not successful. But
|
||||
EventMachine was designed from the ground up with Ruby compatibility in mind,
|
||||
so EM never suffered from the problems that defeated the earlier attempts.
|
||||
|
||||
|
||||
=== [SIDEBAR]: I Heard That EventMachine Doesn't Work Very Well On Windows.
|
||||
|
||||
This too is incorrect. EventMachine is an extension written in C++ and Java,
|
||||
and therefore it requires compilation. Many Windows computers (and some Unix
|
||||
computers, especially in production environments) don't have a build stack.
|
||||
Attempting to install EventMachine on a machine without a compiler usually
|
||||
produces a confusing error.
|
||||
|
||||
In addition, Ruby has a much-debated issue with Windows compiler versions.
|
||||
Ruby on Windows works best with Visual Studio 6, a compiler version that is
|
||||
long out-of-print, no longer supported by Microsoft, and difficult to obtain.
|
||||
(This problem is not specific to EventMachine.)
|
||||
|
||||
Shortly after EventMachine was first released, the compiler issues led to
|
||||
criticism that EM was incompatible with Windows. Since that time, every
|
||||
EventMachine release has been supplied in a precompiled binary form for
|
||||
Windows users, that does not require you to compile the code yourself. EM
|
||||
binary Gems for Windows are compiled using Visual Studio 6.
|
||||
|
||||
EventMachine does supply some advanced features (such as Linux EPOLL support,
|
||||
reduced-privilege operation, UNIX-domain sockets, etc.) that have no
|
||||
meaningful implementation on Windows. Apart from these special cases, all EM
|
||||
functionality (including lightweight concurrency) works perfectly well on
|
||||
Windows.
|
||||
|
||||
Reference in New Issue
Block a user