--- AnyEvent/lib/AnyEvent.pm 2008/04/25 14:24:29 1.90 +++ AnyEvent/lib/AnyEvent.pm 2008/05/10 01:04:42 1.112 @@ -2,7 +2,7 @@ AnyEvent - provide framework for multiple event loops -EV, Event, Coro::EV, Coro::Event, Glib, Tk, Perl, Event::Lib, Qt, POE - various supported event loops +EV, Event, Glib, Tk, Perl, Event::Lib, Qt, POE - various supported event loops =head1 SYNOPSIS @@ -17,8 +17,8 @@ }); my $w = AnyEvent->condvar; # stores whether a condition was flagged - $w->wait; # enters "main loop" till $condvar gets ->broadcast - $w->broadcast; # wake up current and all future wait's + $w->wait; # enters "main loop" till $condvar gets ->send + $w->send; # wake up current and all future wait's =head1 WHY YOU SHOULD USE THIS MODULE (OR NOT) @@ -68,7 +68,6 @@ useful) and you want to force your users to use the one and only event model, you should I use this module. - =head1 DESCRIPTION L provides an identical interface to multiple event loops. This @@ -81,7 +80,7 @@ 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, +following modules is already loaded: L, 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 Tk, Event::Lib, Qt and POE as the pure perl @@ -291,7 +290,7 @@ cb => sub { my ($pid, $status) = @_; warn "pid $pid exited with status $status"; - $done->broadcast; + $done->send; }, ); @@ -300,39 +299,177 @@ =head2 CONDITION VARIABLES -Condition variables can be created by calling the C<< AnyEvent->condvar >> -method without any arguments. - -A condition variable waits for a condition - precisely that the C<< -->broadcast >> method has been called. +If you are familiar with some event loops you will know that all of them +require you to run some blocking "loop", "run" or similar function that +will actively watch for new events and call your callbacks. + +AnyEvent is different, it expects somebody else to run the event loop and +will only block when necessary (usually when told by the user). + +The instrument to do that is called a "condition variable", so called +because they represent a condition that must become true. + +Condition variables can be created by calling the C<< AnyEvent->condvar +>> method, usually without arguments. The only argument pair allowed is +C, which specifies a callback to be called when the condition variable +becomes true. + +After creation, the conditon variable is "false" until it becomes "true" +by calling the C method. + +Condition variables are similar to callbacks, except that you can +optionally wait for them. They can also be called merge points - points +in time where multiple outstandign events have been processed. And yet +another way to call them is transations - each condition variable can be +used to represent a transaction, which finishes at some point and delivers +a result. -They are very useful to signal that a condition has been fulfilled, for -example, if you write a module that does asynchronous http requests, +Condition variables are very useful to signal that something has finished, +for example, if you write a module that does asynchronous http requests, then a condition variable would be the ideal candidate to signal the -availability of results. +availability of results. The user can either act when the callback is +called or can synchronously C<< ->wait >> for the results. -You can also use condition variables to block your main program until -an event occurs - for example, you could C<< ->wait >> in your main -program until the user clicks the Quit button in your app, which would C<< -->broadcast >> the "quit" event. +You can also use them to simulate traditional event loops - for example, +you can block your main program until an event occurs - for example, you +could C<< ->wait >> in your main program until the user clicks the Quit +button of your app, which would C<< ->send >> the "quit" event. Note that condition variables recurse into the event loop - if you have -two pirces of code that call C<< ->wait >> in a round-robbin fashion, you +two pieces of code that call C<< ->wait >> in a round-robbin fashion, you lose. Therefore, condition variables are good to export to your caller, but you should avoid making a blocking wait yourself, at least in callbacks, as this asks for trouble. -This object has two methods: +Condition variables are represented by hash refs in perl, and the keys +used by AnyEvent itself are all named C<_ae_XXX> to make subclassing +easy (it is often useful to build your own transaction class on top of +AnyEvent). To subclass, use C as base class and call +it's C method in your own C method. + +There are two "sides" to a condition variable - the "producer side" which +eventually calls C<< -> send >>, and the "consumer side", which waits +for the send to occur. + +Example: + + # wait till the result is ready + my $result_ready = AnyEvent->condvar; + + # do something such as adding a timer + # or socket watcher the calls $result_ready->send + # when the "result" is ready. + # in this case, we simply use a timer: + my $w = AnyEvent->timer ( + after => 1, + cb => sub { $result_ready->send }, + ); + + # this "blocks" (while handling events) till the callback + # calls send + $result_ready->wait; + +=head3 METHODS FOR PRODUCERS + +These methods should only be used by the producing side, i.e. the +code/module that eventually sends the signal. Note that it is also +the producer side which creates the condvar in most cases, but it isn't +uncommon for the consumer to create it as well. + +=over 4 + +=item $cv->send (...) + +Flag the condition as ready - a running C<< ->wait >> and all further +calls to C will (eventually) return after this method has been +called. If nobody is waiting the send will be remembered. + +If a callback has been set on the condition variable, it is called +immediately from within send. + +Any arguments passed to the C call will be returned by all +future C<< ->wait >> calls. + +=item $cv->croak ($error) + +Similar to send, but causes all call's wait C<< ->wait >> to invoke +C with the given error message/object/scalar. + +This can be used to signal any errors to the condition variable +user/consumer. + +=item $cv->begin ([group callback]) + +=item $cv->end + +These two methods can be used to combine many transactions/events into +one. For example, a function that pings many hosts in parallel might want +to use a condition variable for the whole process. + +Every call to C<< ->begin >> will increment a counter, and every call to +C<< ->end >> will decrement it. If the counter reaches C<0> in C<< ->end +>>, the (last) callback passed to C will be executed. That callback +is I to call C<< ->send >>, but that is not required. If no +callback was set, C will be called without any arguments. + +Let's clarify this with the ping example: + + my $cv = AnyEvent->condvar; + + my %result; + $cv->begin (sub { $cv->send (\%result) }); + + for my $host (@list_of_hosts) { + $cv->begin; + ping_host_then_call_callback $host, sub { + $result{$host} = ...; + $cv->end; + }; + } + + $cv->end; + +This code fragment supposedly pings a number of hosts and calls +C after results for all then have have been gathered - in any +order. To achieve this, the code issues a call to C when it starts +each ping request and calls C when it has received some result for +it. Since C and C only maintain a counter, the order in which +results arrive is not relevant. + +There is an additional bracketing call to C and C outside the +loop, which serves two important purposes: first, it sets the callback +to be called once the counter reaches C<0>, and second, it ensures that +C is called even when C hosts are being pinged (the loop +doesn't execute once). + +This is the general pattern when you "fan out" into multiple subrequests: +use an outer C/C pair to set the callback and ensure C +is called at least once, and then, for each subrequest you start, call +C and for eahc subrequest you finish, call C. + +=back + +=head3 METHODS FOR CONSUMERS + +These methods should only be used by the consuming side, i.e. the +code awaits the condition. =over 4 =item $cv->wait -Wait (blocking if necessary) until the C<< ->broadcast >> method has been -called on c<$cv>, while servicing other watchers normally. +Wait (blocking if necessary) until the C<< ->send >> or C<< ->croak +>> methods have been called on c<$cv>, while servicing other watchers +normally. -You can only wait once on a condition - additional calls will return -immediately. +You can only wait once on a condition - additional calls are valid but +will return immediately. + +If an error condition has been set by calling C<< ->croak >>, then this +function will call C. + +In list context, all parameters passed to C will be returned, +in scalar context only the first one will be returned. Not all event models support a blocking wait - some die in that case (programs might want to do that to stay interactive), so I to C<< ->wait >> in a module is that you cannot sensibly have two C<< ->wait >>'s in parallel, as that would require multiple interpreters or coroutines/threads, none of which C -can supply (the coroutine-aware backends L and -L explicitly support concurrent C<< ->wait >>'s -from different coroutines, however). +can supply. -=item $cv->broadcast +The L module, however, I and I supply coroutines and, in +fact, L replaces AnyEvent's condvars by coroutine-safe +versions and also integrates coroutines into AnyEvent, making blocking +C<< ->wait >> calls perfectly safe as long as they are done from another +coroutine (one that doesn't run the event loop). -Flag the condition as ready - a running C<< ->wait >> and all further -calls to C will (eventually) return after this method has been -called. If nobody is waiting the broadcast will be remembered.. +You can ensure that C<< -wait >> never blocks by setting a callback and +only calling C<< ->wait >> from within that callback (or at a later +time). This will work even when the event loop does not support blocking +waits otherwise. -=back +=item $bool = $cv->ready -Example: +Returns true when the condition is "true", i.e. whether C or +C have been called. - # wait till the result is ready - my $result_ready = AnyEvent->condvar; +=item $cb = $cv->cb ([new callback]) - # do something such as adding a timer - # or socket watcher the calls $result_ready->broadcast - # when the "result" is ready. - # in this case, we simply use a timer: - my $w = AnyEvent->timer ( - after => 1, - cb => sub { $result_ready->broadcast }, - ); +This is a mutator function that returns the callback set and optionally +replaces it before doing so. - # this "blocks" (while handling events) till the watcher - # calls broadcast - $result_ready->wait; +The callback will be called when the condition becomes "true", i.e. when +C or C are called. Calling C inside the callback +or at any later time is guaranteed not to block. + +=back =head1 GLOBAL VARIABLES AND FUNCTIONS @@ -389,12 +525,10 @@ The known classes so far are: - 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, best choice). AnyEvent::Impl::Event based on Event, second best choice. + AnyEvent::Impl::Perl pure-perl implementation, fast and portable. AnyEvent::Impl::Glib based on Glib, third-best choice. - AnyEvent::Impl::Perl pure-perl implementation, inefficient but portable. AnyEvent::Impl::Tk based on Tk, very bad choice. AnyEvent::Impl::Qt based on Qt, cannot be autoprobed (see its docs). AnyEvent::Impl::EventLib based on Event::Lib, leaks memory and worse. @@ -417,6 +551,27 @@ have created an AnyEvent watcher anyway, that is, as late as possible at runtime. +=item $guard = AnyEvent::post_detect { BLOCK } + +Arranges for the code block to be executed as soon as the event model is +autodetected (or immediately if this has already happened). + +If called in scalar or list context, then it creates and returns an object +that automatically removes the callback again when it is destroyed. See +L for a case where this is useful. + +=item @AnyEvent::post_detect + +If there are any code references in this array (you can C to it +before or after loading AnyEvent), then they will called directly after +the event loop has been chosen. + +You should check C<$AnyEvent::MODEL> before adding to this array, though: +if it contains a true value then the event loop has already been detected, +and the array will be ignored. + +Best use C instead. + =back =head1 WHAT TO DO IN A MODULE @@ -430,7 +585,7 @@ to load the event module first. Never call C<< ->wait >> on a condition variable unless you I that -the C<< ->broadcast >> method has been called on it already. This is +the C<< ->send >> method has been called on it already. This is because it will stall the whole program, and the whole point of using events is to stay interactive. @@ -460,6 +615,78 @@ loading the C module, which gives you similar behaviour everywhere, but letting AnyEvent chose is generally better. +=head1 OTHER MODULES + +The following is a non-exhaustive list of additional modules that use +AnyEvent and can therefore be mixed easily with other AnyEvent modules +in the same program. Some of the modules come with AnyEvent, some are +available via CPAN. + +=over 4 + +=item L + +Contains various utility functions that replace often-used but blocking +functions such as C by event-/callback-based versions. + +=item L + +Provide read and write buffers and manages watchers for reads and writes. + +=item L + +Provides a means to do non-blocking connects, accepts etc. + +=item L + +Provides a simple web application server framework. + +=item L + +Provides asynchronous DNS resolver capabilities, beyond what +L offers. + +=item L + +The fastest ping in the west. + +=item L + +AnyEvent based IRC client module family. + +=item L + +AnyEvent based XMPP (Jabber protocol) module family. + +=item L + +AnyEvent-based implementation of the Freenet Client Protocol, birthplace +of AnyEvent. + +=item L + +High level API for event-based execution flow control. + +=item L + +Has special support for AnyEvent via L. + +=item L + +The lambda approach to I/O - don't ask, look there. Can use AnyEvent. + +=item L + +Truly asynchronous I/O, should be in the toolbox of every event +programmer. Can be trivially made to use AnyEvent. + +=item L + +Truly asynchronous Berkeley DB access. Can be trivially made to use +AnyEvent. + +=back + =cut package AnyEvent; @@ -469,7 +696,7 @@ use Carp; -our $VERSION = '3.3'; +our $VERSION = '3.4'; our $MODEL; our $AUTOLOAD; @@ -480,22 +707,42 @@ our @REGISTRY; my @models = ( - [Coro::EV:: => AnyEvent::Impl::CoroEV::], - [Coro::Event:: => AnyEvent::Impl::CoroEvent::], [EV:: => AnyEvent::Impl::EV::], [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 + [Glib:: => AnyEvent::Impl::Glib::], [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); +our %method = map +($_ => 1), qw(io timer signal child condvar one_event DESTROY); + +our @post_detect; + +sub post_detect(&) { + my ($cb) = @_; + + if ($MODEL) { + $cb->(); + + 1 + } else { + push @post_detect, $cb; + + defined wantarray + ? bless \$cb, "AnyEvent::Util::Guard" + : () + } +} + +sub AnyEvent::Util::Guard::DESTROY { + @post_detect = grep $_ != ${$_[0]}, @post_detect; +} sub detect() { unless ($MODEL) { @@ -539,12 +786,14 @@ } $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."; + or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: EV, Event or Glib."; } } unshift @ISA, $MODEL; push @{"$MODEL\::ISA"}, "AnyEvent::Base"; + + (shift @post_detect)->() while @post_detect; } $MODEL @@ -896,22 +1145,23 @@ $quit->wait; -=head1 BENCHMARK +=head1 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), 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 I/O watchers (watching STDOUT, a pty, to -become writable, which it is), lets them fire exactly once and destroys -them again. - -Rewriting the benchmark to use many different sockets instead of using -the same filehandle for all I/O watchers results in a much longer runtime -(socket creation is expensive), but qualitatively the same figures, so it -was not used. +over the event loops themselves and to give you an impression of the speed +of various event loops I prepared some benchmarks. + +=head2 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. -=head2 Explanation of the columns +Source code for this benchmark is found as F in the AnyEvent +distribution. + +=head3 Explanation of the columns I is the number of event watchers created/destroyed. Since different event models feature vastly different performances, each event @@ -937,7 +1187,7 @@ I is the time, in microseconds, that it takes to destroy a single watcher. -=head2 Results +=head3 Results name watchers bytes create invoke destroy comment EV/EV 400000 244 0.56 0.46 0.31 EV native interface @@ -945,13 +1195,13 @@ CoroEV/Any 100000 244 2.49 0.44 0.29 coroutines + Coro::Signal Perl/Any 100000 513 4.92 0.87 1.12 pure perl implementation Event/Event 16000 516 31.88 31.30 0.85 Event native interface - Event/Any 16000 936 39.17 33.63 1.43 Event + AnyEvent watchers + Event/Any 16000 590 35.75 31.42 1.08 Event + AnyEvent watchers Glib/Any 16000 1357 98.22 12.41 54.00 quadratic behaviour Tk/Any 2000 1860 26.97 67.98 14.00 SEGV with >> 2000 watchers POE/Event 2000 6644 108.64 736.02 14.73 via POE::Loop::Event POE/Select 2000 6343 94.13 809.12 565.96 via POE::Loop::Select -=head2 Discussion +=head3 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) @@ -960,6 +1210,16 @@ 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. + C is the sole leader regarding speed and memory use, which are both maximal/minimal, respectively. Even when going through AnyEvent, it uses far less memory than any other event loop and is still faster than Event @@ -991,19 +1251,24 @@ hidden memory cost inside the kernel which is not reflected in the figures above). -C, regardless of underlying event loop (whether using its pure -perl select-based backend or the Event module, the POE-EV backend -couldn't be tested because it wasn't working) shows abysmal performance -and memory usage: Watchers use almost 30 times as much memory as -EV watchers, and 10 times as much memory as Event (the high memory +C, regardless of underlying event loop (whether using its pure perl +select-based backend or the Event module, the POE-EV backend couldn't +be tested because it wasn't working) shows abysmal performance and +memory usage with AnyEvent: Watchers use almost 30 times as much memory +as EV watchers, and 10 times as much memory as Event (the high memory requirements are caused by requiring a session for each watcher). Watcher invocation speed is almost 900 times slower than with AnyEvent's pure perl -implementation. The design of the POE adaptor class in AnyEvent can not -really account for this, as session creation overhead is small compared -to execution of the state machine, which is coded pretty optimally within -L. POE simply seems to be abysmally slow. +implementation. -=head2 Summary +The design of the POE adaptor class in AnyEvent can not really account +for the performance issues, though, as session creation overhead is +small compared to execution of the state machine, which is coded pretty +optimally within L (and while everybody agrees that +using multiple sessions is not a good approach, especially regarding +memory usage, even the author of POE could not come up with a faster +design). + +=head3 Summary =over 4 @@ -1020,11 +1285,137 @@ =back +=head2 BENCHMARKING THE LARGE SERVER CASE + +This benchmark atcually benchmarks the event loop itself. It works by +creating a number of "servers": each server consists of a socketpair, a +timeout watcher that gets reset on activity (but never fires), and an I/O +watcher waiting for input on one side of the socket. Each time the socket +watcher reads a byte it will write that byte to a random other "server". + +The effect is that there will be a lot of I/O watchers, only part of which +are active at any one point (so there is a constant number of active +fds for each loop iterstaion, but which fds these are is random). The +timeout is reset each time something is read because that reflects how +most timeouts work (and puts extra pressure on the event loops). + +In this benchmark, we use 10000 socketpairs (20000 sockets), of which 100 +(1%) are active. This mirrors the activity of large servers with many +connections, most of which are idle at any one point in time. + +Source code for this benchmark is found as F in the AnyEvent +distribution. + +=head3 Explanation of the columns + +I is the number of sockets, and twice the number of "servers" (as +each server has a read and write socket end). + +I is the time it takes to create a socketpair (which is +nontrivial) and two watchers: an I/O watcher and a timeout watcher. + +I, the most important value, is the time it takes to handle a +single "request", that is, reading the token from the pipe and forwarding +it to another server. This includes deleting the old timeout and creating +a new one that moves the timeout into the future. + +=head3 Results + + name sockets create request + EV 20000 69.01 11.16 + Perl 20000 73.32 35.87 + Event 20000 212.62 257.32 + Glib 20000 651.16 1896.30 + POE 20000 349.67 12317.24 uses POE::Loop::Event + +=head3 Discussion + +This benchmark I measure scalability and overall performance of the +particular event loop. + +EV is again fastest. Since it is using epoll on my system, the setup time +is relatively high, though. + +Perl surprisingly comes second. It is much faster than the C-based event +loops Event and Glib. + +Event suffers from high setup time as well (look at its code and you will +understand why). Callback invocation also has a high overhead compared to +the C<< $_->() 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. + +=head3 Summary + +=over 4 + +=item * The pure perl implementation performs extremely well. + +=item * Avoid Glib or POE in large projects where performance matters. + +=back + +=head2 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. + +=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 noticably 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 + =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. +because they rely on inefficient but fork-safe C