--- AnyEvent/lib/AnyEvent.pm 2008/04/24 03:10:03 1.56 +++ AnyEvent/lib/AnyEvent.pm 2008/04/25 07:29:42 1.71 @@ -2,7 +2,7 @@ AnyEvent - provide framework for multiple event loops -EV, Event, Coro::EV, Coro::Event, Glib, Tk, Perl, Event::Lib, Qt - various supported event loops +EV, Event, Coro::EV, Coro::Event, Glib, Tk, Perl, Event::Lib, Qt, POE - various supported event loops =head1 SYNOPSIS @@ -82,11 +82,13 @@ During the first call of any watcher-creation method, the module tries to detect the currently loaded event loop by probing whether one of the following modules is already loaded: L, L, L, -L, L, L. The first one found is used. If none are found, -the module tries to load these modules in the stated order. The first one -that can be successfully loaded will be used. If, after this, still none -could be found, AnyEvent will fall back to a pure-perl event loop, which -is not very efficient, but should work everywhere. +L, L, L, L, L, L, +L. The first one found is used. If none are found, the module tries +to load these modules (excluding Event::Lib, Qt and POE as the pure perl +adaptor should always succeed) in the order given. The first one that can +be successfully loaded will be used. If, after this, still none could be +found, AnyEvent will fall back to a pure-perl event loop, which is not +very efficient, but should work everywhere. Because AnyEvent first checks for modules that are already loaded, loading an event model explicitly before first using AnyEvent will likely make @@ -208,15 +210,16 @@ in 10 seconds") and based on wallclock time (absolute, "fire at 12 o'clock"). -While most event loops expect timers to specified in a relative way, they use -absolute time internally. This makes a difference when your clock "jumps", -for example, when ntp decides to set your clock backwards from the wrong 2014-01-01 to -2008-01-01, a watcher that you created to fire "after" a second might actually take -six years to finally fire. +While most event loops expect timers to specified in a relative way, they +use absolute time internally. This makes a difference when your clock +"jumps", for example, when ntp decides to set your clock backwards from +the wrong date of 2014-01-01 to 2008-01-01, a watcher that is supposed to +fire "after" a second might actually take six years to finally fire. AnyEvent cannot compensate for this. The only event loop that is conscious -about these issues is L, which offers both relative (ev_timer) and -absolute (ev_periodic) timers. +about these issues is L, which offers both relative (ev_timer, based +on true relative time) and absolute (ev_periodic, based on wallclock time) +timers. AnyEvent always prefers relative timers, if available, matching the AnyEvent API. @@ -227,7 +230,7 @@ I without any C prefix, C is the Perl callback to be invoked whenever a signal occurs. -Multiple signals occurances can be clumped together into one callback +Multiple signal occurances can be clumped together into one callback invocation, and callback invocation will be synchronous. synchronous means that it might take a while until the signal gets handled by the process, but it is guarenteed not to interrupt any other callbacks. @@ -362,6 +365,17 @@ AnyEvent::Impl::Perl pure-perl implementation, inefficient but portable. AnyEvent::Impl::Qt based on Qt, cannot be autoprobed (see its docs). AnyEvent::Impl::EventLib based on Event::Lib, leaks memory and worse. + AnyEvent::Impl::POE based on POE, not generic enough for full support. + +There is no support for WxWidgets, as WxWidgets has no support for +watching file handles. However, you can use WxWidgets through the +POE Adaptor, as POE has a Wx backend that simply polls 20 times per +second, which was considered to be too horrible to even consider for +AnyEvent. Likewise, other POE backends can be used by AnyEvent by using +it's adaptor. + +AnyEvent knows about L and L and will try to use L when +autodetecting them. =item AnyEvent::detect @@ -422,7 +436,7 @@ use Carp; -our $VERSION = '3.12'; +our $VERSION = '3.3'; our $MODEL; our $AUTOLOAD; @@ -439,11 +453,13 @@ [Event:: => AnyEvent::Impl::Event::], [Glib:: => AnyEvent::Impl::Glib::], [Tk:: => AnyEvent::Impl::Tk::], + [Wx:: => AnyEvent::Impl::POE::], + [Prima:: => AnyEvent::Impl::POE::], [AnyEvent::Impl::Perl:: => AnyEvent::Impl::Perl::], -); -my @models_detect = ( - [Qt:: => AnyEvent::Impl::Qt::], # requires special main program + # everything below here will not be autoprobed as the pureperl backend should work everywhere [Event::Lib:: => AnyEvent::Impl::EventLib::], # too buggy + [Qt:: => AnyEvent::Impl::Qt::], # requires special main program + [POE::Kernel:: => AnyEvent::Impl::POE::], # lasciate ogni speranza ); our %method = map +($_ => 1), qw(io timer signal child condvar broadcast wait one_event DESTROY); @@ -457,12 +473,14 @@ if (eval "require $model") { $MODEL = $model; warn "AnyEvent: loaded model '$model' (forced by \$PERL_ANYEVENT_MODEL), using it.\n" if $verbose > 1; + } else { + warn "AnyEvent: unable to load model '$model' (from \$PERL_ANYEVENT_MODEL):\n$@" if $verbose; } } # check for already loaded models unless ($MODEL) { - for (@REGISTRY, @models, @models_detect) { + for (@REGISTRY, @models) { my ($package, $model) = @$_; if (${"$package\::VERSION"} > 0) { if (eval "require $model") { @@ -659,6 +677,14 @@ =item C +By default, AnyEvent will be completely silent except in fatal +conditions. You can set this environment variable to make AnyEvent more +talkative. + +When set to C<1> or higher, causes AnyEvent to warn about unexpected +conditions, such as not being able to load the event model specified by +C. + When set to C<2> or higher, cause AnyEvent to report to STDERR which event model it chooses. @@ -836,6 +862,102 @@ $quit->wait; + +=head1 BENCHMARK + +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), here is a benchmark of various supported +event models natively and with anyevent. The benchmark creates a lot of +timers (with a zero timeout) and io watchers (watching STDOUT, a pty, to +become writable, which it is), lets them fire exactly once and destroys +them again. + +=head2 Explanation of the columns + +I 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. + +I 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. + +I 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. + +I 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 C<< ->broadcast >> a condvar once to +signal the end of this phase. + +I is the time, in microseconds, that it takes to destroy a single +watcher. + +=head2 Results + + name watcher bytes create invoke destroy comment + EV/EV 400000 244 0.56 0.46 0.31 EV native interface + EV/Any 100000 610 3.52 0.91 0.75 EV + AnyEvent watchers + CoroEV/Any 100000 610 3.49 0.92 0.75 coroutines + Coro::Signal + Perl/Any 16000 654 4.64 1.22 0.77 pure perl implementation + Event/Event 16000 523 28.05 21.38 0.86 Event native interface + Event/Any 16000 943 34.43 20.48 1.39 Event + AnyEvent watchers + Glib/Any 16000 1357 96.99 12.55 55.51 quadratic behaviour + Tk/Any 2000 1855 27.01 66.61 14.03 SEGV with >> 2000 watchers + POE/Event 2000 6644 108.15 768.19 14.33 via POE::Loop::Event + POE/Select 2000 6343 94.69 807.65 562.69 via POE::Loop::Select + +=head2 Discussion + +The benchmark does I 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, only a single filehandle +is used (although some of the AnyEvent adaptors dup() its file descriptor +to worka round bugs). + +C is the sole leader regarding speed and memory use, which are both +maximal/minimal, respectively. Even when going through AnyEvent, there is +only one event loop that uses less memory (the C module natively), and +no faster event model, not event C natively. + +The pure perl implementation is hit in a few sweet spots (both the +zero timeout and the use of a single fd hit optimisations in the perl +interpreter and the backend itself). Nevertheless tis shows that it +adds very little overhead in itself. Like any select-based backend its +performance becomes really bad with lots of file descriptors, of course, +but this was not subjetc of this benchmark. + +The C module has a relatively high setup and callback invocation cost, +but overall scores on the third place. + +C's memory usage is quite a bit bit higher, features a faster +callback invocation and overall lands in the same class as C. + +The C 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 dup() +employed by some adaptors is not a big performance issue (it does incur a +hidden memory cost inside the kernel, though). + +C, regardless of backend (wether using its pure perl select-based +backend or the Event backend) shows abysmal performance and memory +usage: Watchers use almost 30 times as much memory as EV watchers, and 10 +times as much memory as both Event or EV via AnyEvent. Watcher invocation +is almost 700 times slower as with AnyEvent's pure perl implementation. + +Summary: using EV through AnyEvent is faster than any other event +loop. The overhead AnyEvent adds can be very small, and you should avoid +POE like the plague if you want performance or reasonable memory usage. + + =head1 FORK Most event libraries are not fork-safe. The ones who are usually are @@ -844,6 +966,7 @@ If you have to fork, you must either do so I creating your first watcher OR you must not use AnyEvent at all in the child. + =head1 SECURITY CONSIDERATIONS AnyEvent can be forced to load any event model via @@ -860,19 +983,21 @@ use AnyEvent; + =head1 SEE ALSO Event modules: L, L, L, L, L, L, L, L, L, L, -L, L. +L, L, L. Implementations: L, L, L, L, L, L, L, L, -L. +L, L. Nontrivial usage examples: L, L. + =head1 AUTHOR Marc Lehmann