AnyEvent

 view release on metacpan or  search on metacpan

lib/AnyEvent.pm  view on Meta::CPAN

=head3 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

=head3 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.

=head3 Summary

=over 4

=item * C-based event loops perform very well with small number of
watchers, as the management overhead dominates.

=back

=head2 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 L<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 :) L<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 F<eg/ae0.pl> and
F<eg/ae2.pl> in the AnyEvent distribution, the remaining benchmarks are
part of the IO::Lambda distribution and were used without any changes.


=head1 SIGNALS

AnyEvent currently installs handlers for these signals:

=over 4

=item SIGCHLD

A handler for C<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.

Additionally, when AnyEvent is loaded and SIGCHLD is set to IGNORE, then
AnyEvent will reset it to default, to avoid losing child exit statuses.

=item SIGPIPE

A no-op handler is installed for C<SIGPIPE> when C<$SIG{PIPE}> is C<undef>
when AnyEvent gets loaded.

The rationale for this is that AnyEvent users usually do not really depend
on SIGPIPE delivery (which is purely an optimisation for shell use, or
badly-written programs), but C<SIGPIPE> can cause spurious and rare
program exits as a lot of people do not expect C<SIGPIPE> when writing to
some random socket.

The rationale for installing a no-op handler as opposed to ignoring it is



( run in 2.455 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )