--- AnyEvent/README 2008/04/19 04:58:14 1.16 +++ AnyEvent/README 2008/05/10 22:30:28 1.20 @@ -1,8 +1,8 @@ NAME AnyEvent - provide framework for multiple event loops - EV, Event, Coro::EV, Coro::Event, Glib, Tk, Perl - various supported - event loops + EV, Event, Glib, Tk, Perl, Event::Lib, Qt, POE - various supported event + loops SYNOPSIS use AnyEvent; @@ -16,8 +16,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->send; # wake up current and all future recv's + $w->recv; # enters "main loop" till $condvar gets ->send WHY YOU SHOULD USE THIS MODULE (OR NOT) Glib, POE, IO::Async, Event... CPAN offers event models by the dozen @@ -77,10 +77,12 @@ 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: Coro::EV, Coro::Event, EV, Event, - Glib, Tk. 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 + following modules is already loaded: EV, Event, Glib, + AnyEvent::Impl::Perl, Tk, Event::Lib, Qt, POE. 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 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. @@ -131,7 +133,7 @@ my variables are only visible after the statement in which they are declared. - IO WATCHERS + I/O WATCHERS You can create an I/O watcher by calling the "AnyEvent->io" method with the following mandatory key-value pairs as arguments: @@ -140,11 +142,13 @@ watcher waiting for "r"eadable or "w"ritable events, respectively. "cb" 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. - - It is not allowed to close a file handle as long as any watcher is - active on the underlying file descriptor. + Although the callback might get passed parameters, their value and + presence is undefined and you cannot rely on them. Portable AnyEvent + callbacks cannot use arguments passed to I/O watcher callbacks. + + The I/O watcher might use the underlying file descriptor or a copy of + it. You must not close a file handle as long as any watcher is active on + the underlying file descriptor. Some event loops issue spurious readyness notifications, so you should always use non-blocking calls when reading/writing from/to your file @@ -164,8 +168,12 @@ with the following mandatory arguments: "after" specifies after how many seconds (fractional values are - supported) should the timer activate. "cb" the callback to invoke in - that case. + supported) the callback should be invoked. "cb" is the callback to + invoke in that case. + + Although the callback might get passed parameters, their value and + presence is undefined and you cannot rely on them. Portable AnyEvent + callbacks cannot use arguments passed to time watcher callbacks. The timer callback will be invoked at most once: if you want a repeating timer you have to create a new watcher (this is a limitation by both Tk @@ -202,12 +210,14 @@ 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. + 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 EV, which offers both relative - (ev_timer) and absolute (ev_periodic) timers. + (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. @@ -217,7 +227,11 @@ *name* without any "SIG" prefix, "cb" is the Perl callback to be invoked whenever a signal occurs. - Multiple signals occurances can be clumped together into one callback + Although the callback might get passed parameters, their value and + presence is undefined and you cannot rely on them. Portable AnyEvent + callbacks cannot use arguments passed to signal watcher callbacks. + + 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. @@ -239,49 +253,201 @@ watches for any child process exit). The watcher will trigger as often as status change for the child are received. This works by installing a signal handler for "SIGCHLD". The callback will be called with the pid - and exit status (as returned by waitpid). + and exit status (as returned by waitpid), so unlike other watcher types, + you *can* rely on child watcher callback arguments. + + There is a slight catch to child watchers, however: you usually start + them *after* the child process was created, and this means the process + could have exited already (and no SIGCHLD will be sent anymore). + + Not all event models handle this correctly (POE doesn't), but even for + event models that *do* handle this correctly, they usually need to be + loaded before the process exits (i.e. before you fork in the first + place). + + This means you cannot create a child watcher as the very first thing in + an AnyEvent program, you *have* to create at least one watcher before + you "fork" the child (alternatively, you can call "AnyEvent::detect"). - Example: wait for pid 1333 + Example: fork a process and wait for it + + my $done = AnyEvent->condvar; + + my $pid = fork or exit 5; my $w = AnyEvent->child ( - pid => 1333, + pid => $pid, cb => sub { my ($pid, $status) = @_; warn "pid $pid exited with status $status"; + $done->send; }, ); + # do something else, then wait for process exit + $done->recv; + CONDITION VARIABLES - Condition variables can be created by calling the "AnyEvent->condvar" - method without any arguments. + 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). - A condition variable waits for a condition - precisely that the - "->broadcast" method has been called. + The instrument to do that is called a "condition variable", so called + because they represent a condition that must become true. - They are very useful to signal that a condition has been fulfilled, 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. - - You can also use condition variables to block your main program until an - event occurs - for example, you could "->wait" in your main program - until the user clicks the Quit button in your app, which would - "->broadcast" the "quit" event. + Condition variables can be created by calling the "AnyEvent->condvar" + method, usually without arguments. The only argument pair allowed is + "cb", 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 "send" 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. + + 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. The user can either act when the + callback is called or can synchronously "->recv" for the results. + + 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 "->recv" in your main program until the user clicks the Quit + button of your app, which would "->send" the "quit" event. Note that condition variables recurse into the event loop - if you have - two pirces of code that call "->wait" in a round-robbin fashion, you + two pieces of code that call "->recv" 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 "_ae_XXX" to make subclassing easy + (it is often useful to build your own transaction class on top of + AnyEvent). To subclass, use "AnyEvent::CondVar" as base class and call + it's "new" method in your own "new" method. + + There are two "sides" to a condition variable - the "producer side" + which eventually calls "-> 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 }, + ); - $cv->wait - Wait (blocking if necessary) until the "->broadcast" method has been - called on c<$cv>, while servicing other watchers normally. + # this "blocks" (while handling events) till the callback + # calls send + $result_ready->recv; + + 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. + + $cv->send (...) + Flag the condition as ready - a running "->recv" and all further + calls to "recv" 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 "send" call will be returned by all + future "->recv" calls. + + $cv->croak ($error) + Similar to send, but causes all call's to "->recv" to invoke + "Carp::croak" with the given error message/object/scalar. + + This can be used to signal any errors to the condition variable + user/consumer. + + $cv->begin ([group callback]) + $cv->end + These two methods are EXPERIMENTAL and MIGHT CHANGE. + + 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 "->begin" will increment a counter, and every call to + "->end" will decrement it. If the counter reaches 0 in "->end", the + (last) callback passed to "begin" will be executed. That callback is + *supposed* to call "->send", but that is not required. If no + callback was set, "send" 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 + "send" after results for all then have have been gathered - in any + order. To achieve this, the code issues a call to "begin" when it + starts each ping request and calls "end" when it has received some + result for it. Since "begin" and "end" only maintain a counter, the + order in which results arrive is not relevant. + + There is an additional bracketing call to "begin" and "end" outside + the loop, which serves two important purposes: first, it sets the + callback to be called once the counter reaches 0, and second, it + ensures that "send" is called even when "no" 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 "begin"/"end" pair to set the callback and + ensure "end" is called at least once, and then, for each subrequest + you start, call "begin" and for eahc subrequest you finish, call + "end". + + METHODS FOR CONSUMERS + These methods should only be used by the consuming side, i.e. the code + awaits the condition. + + $cv->recv + Wait (blocking if necessary) until the "->send" or "->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 "->croak", then this + function will call "croak". + + In list context, all parameters passed to "send" 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 *if you are @@ -292,35 +458,33 @@ will not block, while still suppporting blocking waits if the caller so desires). - Another reason *never* to "->wait" in a module is that you cannot - sensibly have two "->wait"'s in parallel, as that would require + Another reason *never* to "->recv" in a module is that you cannot + sensibly have two "->recv"'s in parallel, as that would require multiple interpreters or coroutines/threads, none of which - "AnyEvent" can supply (the coroutine-aware backends - AnyEvent::Impl::CoroEV and AnyEvent::Impl::CoroEvent explicitly - support concurrent "->wait"'s from different coroutines, however). - - $cv->broadcast - Flag the condition as ready - a running "->wait" and all further - calls to "wait" will (eventually) return after this method has been - called. If nobody is waiting the broadcast will be remembered.. - - Example: + "AnyEvent" can supply. - # 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->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 "blocks" (while handling events) till the watcher - # calls broadcast - $result_ready->wait; + The Coro module, however, *can* and *does* supply coroutines and, in + fact, Coro::AnyEvent replaces AnyEvent's condvars by coroutine-safe + versions and also integrates coroutines into AnyEvent, making + blocking "->recv" calls perfectly safe as long as they are done from + another coroutine (one that doesn't run the event loop). + + You can ensure that "-recv" never blocks by setting a callback and + only calling "->recv" from within that callback (or at a later + time). This will work even when the event loop does not support + blocking waits otherwise. + + $bool = $cv->ready + Returns true when the condition is "true", i.e. whether "send" or + "croak" have been called. + + $cb = $cv->cb ([new callback]) + This is a mutator function that returns the callback set and + optionally replaces it before doing so. + + The callback will be called when the condition becomes "true", i.e. + when "send" or "croak" are called. Calling "recv" inside the + callback or at any later time is guaranteed not to block. GLOBAL VARIABLES AND FUNCTIONS $AnyEvent::MODEL @@ -332,13 +496,24 @@ 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, 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::Perl pure-perl implementation, fast and portable. 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 Prima and Wx and will try to use POE when + autodetecting them. AnyEvent::detect Returns $AnyEvent::MODEL, forcing autodetection of the event model @@ -346,6 +521,25 @@ would have created an AnyEvent watcher anyway, that is, as late as possible at runtime. + $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 Coro::BDB for a case where this is useful. + + @AnyEvent::post_detect + If there are any code references in this array (you can "push" to it + before or after loading AnyEvent), then they will called directly + after the event loop has been chosen. + + You should check $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 "AnyEvent::post_detect { BLOCK }" instead. + WHAT TO DO IN A MODULE As a module author, you should "use AnyEvent" and call AnyEvent methods freely, but you should not load a specific event module or rely on it. @@ -355,14 +549,14 @@ so by calling AnyEvent in your module body you force the user of your module to load the event module first. - Never call "->wait" on a condition variable unless you *know* that the - "->broadcast" 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. + Never call "->recv" on a condition variable unless you *know* that the + "->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. - It is fine, however, to call "->wait" when the user of your module + It is fine, however, to call "->recv" when the user of your module requests it (i.e. if you create a http request object ad have a method - called "results" that returns the results, it should call "->wait" + called "results" that returns the results, it should call "->recv" freely, as the user of your module knows what she is doing. always). WHAT TO DO IN THE MAIN PROGRAM @@ -387,6 +581,60 @@ loading the "AnyEvent::Impl::Perl" module, which gives you similar behaviour everywhere, but letting AnyEvent chose is generally better. +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. + + AnyEvent::Util + Contains various utility functions that replace often-used but + blocking functions such as "inet_aton" by event-/callback-based + versions. + + AnyEvent::Handle + Provide read and write buffers and manages watchers for reads and + writes. + + AnyEvent::HTTPD + Provides a simple web application server framework. + + AnyEvent::DNS + Provides asynchronous DNS resolver capabilities, beyond what + AnyEvent::Util offers. + + AnyEvent::FastPing + The fastest ping in the west. + + Net::IRC3 + AnyEvent based IRC client module family. + + Net::XMPP2 + AnyEvent based XMPP (Jabber protocol) module family. + + Net::FCP + AnyEvent-based implementation of the Freenet Client Protocol, + birthplace of AnyEvent. + + Event::ExecFlow + High level API for event-based execution flow control. + + Coro + Has special support for AnyEvent via Coro::AnyEvent. + + AnyEvent::AIO, IO::AIO + Truly asynchronous I/O, should be in the toolbox of every event + programmer. AnyEvent::AIO transparently fuses IO::AIO and AnyEvent + together. + + AnyEvent::BDB, BDB + Truly asynchronous Berkeley DB access. AnyEvent::AIO transparently + fuses IO::AIO and AnyEvent together. + + IO::Lambda + The lambda approach to I/O - don't ask, look there. Can use + AnyEvent. + SUPPLYING YOUR OWN EVENT MODEL INTERFACE This is an advanced topic that you do not normally need to use AnyEvent in a module. This section is only of use to event loop authors who want @@ -433,11 +681,35 @@ ENVIRONMENT VARIABLES The following environment variables are used by this module: - "PERL_ANYEVENT_VERBOSE" when set to 2 or higher, cause AnyEvent to - report to STDERR which event model it chooses. + "PERL_ANYEVENT_VERBOSE" + 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 1 or higher, causes AnyEvent to warn about unexpected + conditions, such as not being able to load the event model specified + by "PERL_ANYEVENT_MODEL". + + When set to 2 or higher, cause AnyEvent to report to STDERR which + event model it chooses. + + "PERL_ANYEVENT_MODEL" + 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 "AnyEvent::Impl::" + 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 (AnyEvent::Impl::Perl) you + could start your program like this: + + PERL_ANYEVENT_MODEL=Perl perl ... EXAMPLE PROGRAM - The following program uses an IO watcher to read data from STDIN, a + The following program uses an I/O watcher to read data from STDIN, a timer to display a message once per second, and a condition variable to quit the program when the user enters quit: @@ -590,14 +862,287 @@ $quit->wait; +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. + + 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 "->broadcast" 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 400000 244 0.56 0.46 0.31 EV native interface + EV/Any 100000 244 2.50 0.46 0.29 EV + AnyEvent watchers + 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 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 + + 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. Even when going through AnyEvent, it 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. + + "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 + dup() employed by some adaptors is not a big performance issue (it does + incur a hidden memory cost inside the kernel which is not reflected in + the figures above). + + "POE", 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 the performance issues, though, as session creation overhead is + small compared to execution of the state machine, which is coded pretty + optimally within AnyEvent::Impl::POE (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). + + Summary + * Using EV through AnyEvent is faster than any other event loop (even + when used without AnyEvent), but most event loops have acceptable + performance with or without AnyEvent. + + * The overhead AnyEvent adds is usually much smaller than the overhead + of the actual event loop, only with extremely fast event loops such + as EV adds AnyEvent significant overhead. + + * You should avoid POE like the plague if you want performance or + reasonable memory usage. + + 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 eg/bench2 in the AnyEvent + distribution. + + Explanation of the columns + *sockets* is the number of sockets, and twice the number of "servers" + (as each server has a read and write socket end). + + *create* is the time it takes to create a socketpair (which is + nontrivial) and two watchers: an I/O watcher and a timeout watcher. + + *request*, 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. + + 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 + + Discussion + This benchmark *does* 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 "$_->() 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. + + Summary + * The pure perl implementation performs extremely well. + + * Avoid Glib or POE in large projects where performance matters. + + 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. + + 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 + + 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. + + Summary + * C-based event loops perform very well with small number of watchers, + as the management overhead dominates. + +FORK + Most event libraries are not fork-safe. The ones who are usually are + because they rely on inefficient but fork-safe "select" or "poll" calls. + Only EV is fully fork-aware. + + If you have to fork, you must either do so *before* creating your first + watcher OR you must not use AnyEvent at all in the child. + +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 "BEGIN" block: + + BEGIN { delete $ENV{PERL_ANYEVENT_MODEL} } + + use AnyEvent; + + Similar considerations apply to $ENV{PERL_ANYEVENT_VERBOSE}, as that can + be used to probe what backend is used and gain other information (which + is probably even less useful to an attacker than PERL_ANYEVENT_MODEL). + SEE ALSO - Event modules: Coro::EV, EV, EV::Glib, Glib::EV, Coro::Event, Event, - Glib::Event, Glib, Coro, Tk. + Event modules: EV, EV::Glib, Glib::EV, Event, Glib::Event, Glib, Tk, + Event::Lib, Qt, POE. + + Implementations: AnyEvent::Impl::EV, AnyEvent::Impl::Event, + AnyEvent::Impl::Glib, AnyEvent::Impl::Tk, AnyEvent::Impl::Perl, + AnyEvent::Impl::EventLib, AnyEvent::Impl::Qt, AnyEvent::Impl::POE. - Implementations: AnyEvent::Impl::CoroEV, AnyEvent::Impl::EV, - AnyEvent::Impl::CoroEvent, AnyEvent::Impl::Event, AnyEvent::Impl::Glib, - AnyEvent::Impl::Tk, AnyEvent::Impl::Perl. + Coroutine support: Coro, Coro::AnyEvent, Coro::EV, Coro::Event, Nontrivial usage examples: Net::FCP, Net::XMPP2. +AUTHOR + Marc Lehmann + http://home.schmorp.de/