AnyEvent
view release on metacpan or search on metacpan
compared to the "$_->() for .."-style loop that the Perl event loop
uses. Event uses select or poll in basically all documented
configurations.
Glib is hit hard by its quadratic behaviour w.r.t. many watchers. It
clearly fails to perform with many filehandles or in busy servers.
POE is still completely out of the picture, taking over 1000 times as
long as EV, and over 100 times as long as the Perl implementation, even
though it uses a C-based event loop in this case.
Summary
* The pure perl implementation performs extremely well.
* Avoid Glib or POE in large projects where performance matters.
BENCHMARKING SMALL SERVERS
While event loops should scale (and select-based ones do not...) even to
large servers, most programs we (or I :) actually write have only a few
I/O watchers.
In this benchmark, I use the same benchmark program as in the large
server case, but it uses only eight "servers", of which three are active
at any one time. This should reflect performance for a small server
relatively well.
The columns are identical to the previous table.
Results
name sockets create request
EV 16 20.00 6.54
Perl 16 25.75 12.62
Event 16 81.27 35.86
Glib 16 32.63 15.48
POE 16 261.87 276.28 uses POE::Loop::Event
Discussion
The benchmark tries to test the performance of a typical small server.
While knowing how various event loops perform is interesting, keep in
mind that their overhead in this case is usually not as important, due
to the small absolute number of watchers (that is, you need efficiency
and speed most when you have lots of watchers, not when you only have a
few of them).
EV is again fastest.
Perl again comes second. It is noticeably faster than the C-based event
loops Event and Glib, although the difference is too small to really
matter.
POE also performs much better in this case, but is is still far behind
the others.
Summary
* C-based event loops perform very well with small number of watchers,
as the management overhead dominates.
THE IO::Lambda BENCHMARK
Recently I was told about the benchmark in the IO::Lambda manpage, which
could be misinterpreted to make AnyEvent look bad. In fact, the
benchmark simply compares IO::Lambda with POE, and IO::Lambda looks
better (which shouldn't come as a surprise to anybody). As such, the
benchmark is fine, and mostly shows that the AnyEvent backend from
IO::Lambda isn't very optimal. But how would AnyEvent compare when used
without the extra baggage? To explore this, I wrote the equivalent
benchmark for AnyEvent.
The benchmark itself creates an echo-server, and then, for 500 times,
connects to the echo server, sends a line, waits for the reply, and then
creates the next connection. This is a rather bad benchmark, as it
doesn't test the efficiency of the framework or much non-blocking I/O,
but it is a benchmark nevertheless.
name runtime
Lambda/select 0.330 sec
+ optimized 0.122 sec
Lambda/AnyEvent 0.327 sec
+ optimized 0.138 sec
Raw sockets/select 0.077 sec
POE/select, components 0.662 sec
POE/select, raw sockets 0.226 sec
POE/select, optimized 0.404 sec
AnyEvent/select/nb 0.085 sec
AnyEvent/EV/nb 0.068 sec
+state machine 0.134 sec
The benchmark is also a bit unfair (my fault): the IO::Lambda/POE
benchmarks actually make blocking connects and use 100% blocking I/O,
defeating the purpose of an event-based solution. All of the newly
written AnyEvent benchmarks use 100% non-blocking connects (using
AnyEvent::Socket::tcp_connect and the asynchronous pure perl DNS
resolver), so AnyEvent is at a disadvantage here, as non-blocking
connects generally require a lot more bookkeeping and event handling
than blocking connects (which involve a single syscall only).
The last AnyEvent benchmark additionally uses AnyEvent::Handle, which
offers similar expressive power as POE and IO::Lambda, using
conventional Perl syntax. This means that both the echo server and the
client are 100% non-blocking, further placing it at a disadvantage.
As you can see, the AnyEvent + EV combination even beats the
hand-optimised "raw sockets benchmark", while AnyEvent + its pure perl
backend easily beats IO::Lambda and POE.
And even the 100% non-blocking version written using the high-level (and
slow :) AnyEvent::Handle abstraction beats both POE and IO::Lambda
higher level ("unoptimised") abstractions by a large margin, even though
it does all of DNS, tcp-connect and socket I/O in a non-blocking way.
The two AnyEvent benchmarks programs can be found as eg/ae0.pl and
eg/ae2.pl in the AnyEvent distribution, the remaining benchmarks are
part of the IO::Lambda distribution and were used without any changes.
SIGNALS
AnyEvent currently installs handlers for these signals:
SIGCHLD
A handler for "SIGCHLD" is installed by AnyEvent's child watcher
emulation for event loops that do not support them natively. Also,
some event loops install a similar handler.
( run in 1.907 second using v1.01-cache-2.11-cpan-39bf76dae61 )