AnyEvent

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN


       EV::run;

    3b. The module user could use AnyEvent, too:

       use AnyEvent;

       my $quit = AnyEvent->condvar;

       $fcp->txn_client_get ($url)->cb (sub {
          ...
          $quit->send;
       });

       $quit->recv;

BENCHMARKS
    To give you an idea of the performance and overheads that AnyEvent adds
    over the event loops themselves and to give you an impression of the
    speed of various event loops I prepared some benchmarks.

  BENCHMARKING ANYEVENT OVERHEAD
    Here is a benchmark of various supported event models used natively and
    through AnyEvent. The benchmark creates a lot of timers (with a zero
    timeout) and I/O watchers (watching STDOUT, a pty, to become writable,
    which it is), lets them fire exactly once and destroys them again.

    Source code for this benchmark is found as eg/bench in the AnyEvent
    distribution. It uses the AE interface, which makes a real difference
    for the EV and Perl backends only.

   Explanation of the columns
    *watcher* is the number of event watchers created/destroyed. Since
    different event models feature vastly different performances, each event
    loop was given a number of watchers so that overall runtime is
    acceptable and similar between tested event loop (and keep them from
    crashing): Glib would probably take thousands of years if asked to
    process the same number of watchers as EV in this benchmark.

    *bytes* is the number of bytes (as measured by the resident set size,
    RSS) consumed by each watcher. This method of measuring captures both C
    and Perl-based overheads.

    *create* is the time, in microseconds (millionths of seconds), that it
    takes to create a single watcher. The callback is a closure shared
    between all watchers, to avoid adding memory overhead. That means
    closure creation and memory usage is not included in the figures.

    *invoke* is the time, in microseconds, used to invoke a simple callback.
    The callback simply counts down a Perl variable and after it was invoked
    "watcher" times, it would "->send" a condvar once to signal the end of
    this phase.

    *destroy* is the time, in microseconds, that it takes to destroy a
    single watcher.

   Results
              name watchers bytes create invoke destroy comment
             EV/EV   100000   223   0.47   0.43    0.27 EV native interface
            EV/Any   100000   223   0.48   0.42    0.26 EV + AnyEvent watchers
      Coro::EV/Any   100000   223   0.47   0.42    0.26 coroutines + Coro::Signal
          Perl/Any   100000   431   2.70   0.74    0.92 pure perl implementation
       Event/Event    16000   516  31.16  31.84    0.82 Event native interface
         Event/Any    16000  1203  42.61  34.79    1.80 Event + AnyEvent watchers
       IOAsync/Any    16000  1911  41.92  27.45   16.81 via IO::Async::Loop::IO_Poll
       IOAsync/Any    16000  1726  40.69  26.37   15.25 via IO::Async::Loop::Epoll
          Glib/Any    16000  1118  89.00  12.57   51.17 quadratic behaviour
            Tk/Any     2000  1346  20.96  10.75    8.00 SEGV with >> 2000 watchers
           POE/Any     2000  6951 108.97 795.32   14.24 via POE::Loop::Event
           POE/Any     2000  6648  94.79 774.40  575.51 via POE::Loop::Select

   Discussion
    The benchmark does *not* measure scalability of the event loop very
    well. For example, a select-based event loop (such as the pure perl one)
    can never compete with an event loop that uses epoll when the number of
    file descriptors grows high. In this benchmark, all events become ready
    at the same time, so select/poll-based implementations get an unnatural
    speed boost.

    Also, note that the number of watchers usually has a nonlinear effect on
    overall speed, that is, creating twice as many watchers doesn't take
    twice the time - usually it takes longer. This puts event loops tested
    with a higher number of watchers at a disadvantage.

    To put the range of results into perspective, consider that on the
    benchmark machine, handling an event takes roughly 1600 CPU cycles with
    EV, 3100 CPU cycles with AnyEvent's pure perl loop and almost 3000000
    CPU cycles with POE.

    "EV" is the sole leader regarding speed and memory use, which are both
    maximal/minimal, respectively. When using the AE API there is zero
    overhead (when going through the AnyEvent API create is about 5-6 times
    slower, with other times being equal, so still uses far less memory than
    any other event loop and is still faster than Event natively).

    The pure perl implementation is hit in a few sweet spots (both the
    constant timeout and the use of a single fd hit optimisations in the
    perl interpreter and the backend itself). Nevertheless this shows that
    it adds very little overhead in itself. Like any select-based backend
    its performance becomes really bad with lots of file descriptors (and
    few of them active), of course, but this was not subject of this
    benchmark.

    The "Event" module has a relatively high setup and callback invocation
    cost, but overall scores in on the third place.

    "IO::Async" performs admirably well, about on par with "Event", even
    when using its pure perl backend.

    "Glib"'s memory usage is quite a bit higher, but it features a faster
    callback invocation and overall ends up in the same class as "Event".
    However, Glib scales extremely badly, doubling the number of watchers
    increases the processing time by more than a factor of four, making it
    completely unusable when using larger numbers of watchers (note that
    only a single file descriptor was used in the benchmark, so
    inefficiencies of "poll" do not account for this).

    The "Tk" adaptor works relatively well. The fact that it crashes with
    more than 2000 watchers is a big setback, however, as correctness takes
    precedence over speed. Nevertheless, its performance is surprising, as
    the file descriptor is dup()ed for each watcher. This shows that the



( run in 1.397 second using v1.01-cache-2.11-cpan-437f7b0c052 )