--- AnyEvent/lib/AnyEvent.pm 2008/04/22 05:12:19 1.54 +++ AnyEvent/lib/AnyEvent.pm 2008/04/25 07:15:09 1.69 @@ -2,7 +2,7 @@ AnyEvent - provide framework for multiple event loops -EV, Event, Coro::EV, Coro::Event, Glib, Tk, Perl - 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 @@ -147,8 +149,8 @@ respectively. C is the callback to invoke each time the file handle becomes ready. -File handles will be kept alive, so as long as the watcher exists, the -file handle exists, too. +As long as the I/O watcher exists it will keep the file descriptor or a +copy of it alive/open. It is not allowed to close a file handle as long as any watcher is active on the underlying file descriptor. @@ -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. @@ -355,11 +358,24 @@ AnyEvent::Impl::CoroEV based on Coro::EV, best choice. AnyEvent::Impl::CoroEvent based on Coro::Event, second best choice. - AnyEvent::Impl::EV based on EV (an interface to libev, also best choice). - AnyEvent::Impl::Event based on Event, also second best choice :) + AnyEvent::Impl::EV based on EV (an interface to libev, best choice). + AnyEvent::Impl::Event based on Event, second best choice. AnyEvent::Impl::Glib based on Glib, third-best choice. AnyEvent::Impl::Tk based on Tk, very bad choice. 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 @@ -420,7 +436,7 @@ use Carp; -our $VERSION = '3.12'; +our $VERSION = '3.3'; our $MODEL; our $AUTOLOAD; @@ -437,43 +453,61 @@ [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::], + # 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 condvar broadcast wait signal one_event DESTROY); +our %method = map +($_ => 1), qw(io timer signal child condvar broadcast wait one_event DESTROY); sub detect() { unless ($MODEL) { no strict 'refs'; - # check for already loaded models - for (@REGISTRY, @models) { - my ($package, $model) = @$_; - if (${"$package\::VERSION"} > 0) { - if (eval "require $model") { - $MODEL = $model; - warn "AnyEvent: found model '$model', using it.\n" if $verbose > 1; - last; - } + if ($ENV{PERL_ANYEVENT_MODEL} =~ /^([a-zA-Z]+)$/) { + my $model = "AnyEvent::Impl::$1"; + 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) { - # try to load a model - for (@REGISTRY, @models) { my ($package, $model) = @$_; - if (eval "require $package" - and ${"$package\::VERSION"} > 0 - and eval "require $model") { - $MODEL = $model; - warn "AnyEvent: autoprobed and loaded model '$model', using it.\n" if $verbose > 1; - last; + if (${"$package\::VERSION"} > 0) { + if (eval "require $model") { + $MODEL = $model; + warn "AnyEvent: autodetected model '$model', using it.\n" if $verbose > 1; + last; + } } } - $MODEL - or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: EV (or Coro+EV), Event (or Coro+Event), Glib or Tk."; + unless ($MODEL) { + # try to load a model + + for (@REGISTRY, @models) { + my ($package, $model) = @$_; + if (eval "require $package" + and ${"$package\::VERSION"} > 0 + and eval "require $model") { + $MODEL = $model; + warn "AnyEvent: autoprobed model '$model', using it.\n" if $verbose > 1; + last; + } + } + + $MODEL + or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: EV (or Coro+EV), Event (or Coro+Event) or Glib."; + } } unshift @ISA, $MODEL; @@ -639,8 +673,38 @@ The following environment variables are used by this module: -C when set to C<2> or higher, cause AnyEvent to -report to STDERR which event model it chooses. +=over 4 + +=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. + +=item C + +This can be used to specify the event model to be used by AnyEvent, before +autodetection and -probing kicks in. It must be a string consisting +entirely of ASCII letters. The string C gets prepended +and the resulting module name is loaded and if the load was successful, +used as event model. If it fails to load AnyEvent will proceed with +autodetection and -probing. + +This functionality might change in future versions. + +For example, to force the pure perl model (L) you +could start your program like this: + + PERL_ANYEVENT_MODEL=Perl perl ... + +=back =head1 EXAMPLE PROGRAM @@ -798,17 +862,141 @@ $quit->wait; + +=head1 BENCHMARK + +To give you an idea of the performance and overheads that AnyEvent adds +over the event loops directly, 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 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 + CoroEV/Any 100000 610 3.49 0.92 0.75 coroutines + Coro::Signal + Perl/Any 10000 654 4.64 1.22 0.77 pure perl implementation + Event/Event 10000 523 28.05 21.38 5.22 Event native interface + Event/Any 10000 943 34.43 20.48 1.39 + 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/Select 2000 6343 94.69 807.65 562.69 POE::Loop::Select + POE/Event 2000 6644 108.15 768.19 14.33 POE::Loop::Event + +=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 +because they are so inefficient. Only L is fully fork-aware. + +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 +$ENV{PERL_ANYEVENT_MODEL}. While this cannot (to my knowledge) be used to +execute arbitrary code or directly gain access, it can easily be used to +make the program hang or malfunction in subtle ways, as AnyEvent watchers +will not be active when the program uses a different event model than +specified in the variable. + +You can make AnyEvent completely ignore this variable by deleting it +before the first watcher gets created, e.g. with a C block: + + BEGIN { delete $ENV{PERL_ANYEVENT_MODEL} } + + use AnyEvent; + + =head1 SEE ALSO Event modules: L, L, L, L, -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, L, L, +L, L. Nontrivial usage examples: L, L. + =head1 AUTHOR Marc Lehmann