--- AnyEvent/lib/AnyEvent.pm 2009/06/23 12:19:33 1.215 +++ AnyEvent/lib/AnyEvent.pm 2009/07/06 23:42:24 1.227 @@ -394,13 +394,17 @@ I 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 I 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 I to create at least one watcher before you -C the child (alternatively, you can call C). +Not all event models handle this correctly (neither POE nor IO::Async do, +see their AnyEvent::Impl manpages for details), but even for event models +that I handle this correctly, they usually need to be loaded before +the process exits (i.e. before you fork in the first place). AnyEvent's +pure perl event loop handles all cases correctly regardless of when you +start the watcher. + +This means you cannot create a child watcher as the very first +thing in an AnyEvent program, you I to create at least one +watcher before you C the child (alternatively, you can call +C). Example: fork a process and wait for it @@ -597,8 +601,6 @@ =item $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. @@ -609,7 +611,37 @@ 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: +You can think of C<< $cv->send >> giving you an OR condition (one call +sends), while C<< $cv->begin >> and C<< $cv->end >> giving you an AND +condition (all C calls must be C'ed before the condvar sends). + +Let's start with a simple example: you have two I/O watchers (for example, +STDOUT and STDERR for a program), and you want to wait for both streams to +close before activating a condvar: + + my $cv = AnyEvent->condvar; + + $cv->begin; # first watcher + my $w1 = AnyEvent->io (fh => $fh1, cb => sub { + defined sysread $fh1, my $buf, 4096 + or $cv->end; + }); + + $cv->begin; # second watcher + my $w2 = AnyEvent->io (fh => $fh2, cb => sub { + defined sysread $fh2, my $buf, 4096 + or $cv->end; + }); + + $cv->recv; + +This works because for every event source (EOF on file handle), there is +one call to C, so the condvar waits for all calls to C before +sending. + +The ping example mentioned above is slightly more complicated, as the +there are results to be passwd back, and the number of tasks that are +begung can potentially be zero: my $cv = AnyEvent->condvar; @@ -639,10 +671,11 @@ 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 each subrequest you finish, call C. +This is the general pattern when you "fan out" into multiple (but +potentially none) 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 each subrequest you finish, +call C. =back @@ -732,6 +765,10 @@ AnyEvent::Impl::EventLib based on Event::Lib, leaks memory and worse. AnyEvent::Impl::POE based on POE, not generic enough for full support. + # warning, support for IO::Async is only partial, as it is too broken + # and limited toe ven support the AnyEvent API. See AnyEvent::Impl::Async. + AnyEvent::Impl::IOAsync based on IO::Async, cannot be autoprobed (see its docs). + 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 @@ -933,7 +970,7 @@ use Carp; -our $VERSION = 4.411; +our $VERSION = 4.8; our $MODEL; our $AUTOLOAD; @@ -976,6 +1013,13 @@ [POE::Kernel:: => AnyEvent::Impl::POE::], # lasciate ogni speranza [Wx:: => AnyEvent::Impl::POE::], [Prima:: => AnyEvent::Impl::POE::], + # IO::Async is just too broken - we would need workaorunds for its + # byzantine signal and broken child handling, among others. + # IO::Async is rather hard to detect, as it doesn't have any + # obvious default class. +# [IO::Async:: => AnyEvent::Impl::IOAsync::], # requires special main program +# [IO::Async::Loop:: => AnyEvent::Impl::IOAsync::], # requires special main program +# [IO::Async::Notifier:: => AnyEvent::Impl::IOAsync::], # requires special main program ); our %method = map +($_ => 1), @@ -1077,7 +1121,7 @@ # utility function to dup a filehandle. this is used by many backends # to support binding more than one watcher per filehandle (they usually # allow only one watcher per fd, so we dup it to get a different one). -sub _dupfh($$$$) { +sub _dupfh($$;$$) { my ($poll, $fh, $r, $w) = @_; # cygwin requires the fh mode to be matching, unix doesn't @@ -1368,12 +1412,12 @@ AnyEvent does not do much argument checking by default, as thorough argument checking is very costly. Setting this variable to a true value will cause AnyEvent to load C and then to thoroughly -check the arguments passed to most method calls. If it finds any problems +check the arguments passed to most method calls. If it finds any problems, it will croak. In other words, enables "strict" mode. -Unlike C, it is definitely recommended ot keep it off in +Unlike C, it is definitely recommended to keep it off in production. Keeping C in your environment while developing programs can be very useful, however. @@ -1429,6 +1473,25 @@ The maximum number of child processes that C will create in parallel. +=item C + +The default value for the C parameter for the default DNS +resolver - this is the maximum number of parallel DNS requests that are +sent to the DNS server. + +=item C + +The file to use instead of F (or OS-specific +configuration) in the default resolver. When set to the empty string, no +default config will be used. + +=item C, C. + +When neither C nor C was specified during +L context creation, and either of these environment +variables exist, they will be used to specify CA certificate locations +instead of a system-dependent default. + =back =head1 SUPPLYING YOUR OWN EVENT MODEL INTERFACE @@ -1682,6 +1745,8 @@ Perl/Any 100000 452 4.13 0.73 0.95 pure perl implementation Event/Event 16000 517 32.20 31.80 0.81 Event native interface Event/Any 16000 590 35.85 31.55 1.06 Event + AnyEvent watchers + IOAsync/Any 16000 989 38.10 32.77 11.13 via IO::Async::Loop::IO_Poll + IOAsync/Any 16000 990 37.59 29.50 10.61 via IO::Async::Loop::Epoll Glib/Any 16000 1357 102.33 12.31 51.00 quadratic behaviour Tk/Any 2000 1860 27.20 66.31 14.00 SEGV with >> 2000 watchers POE/Event 2000 6328 109.99 751.67 14.02 via POE::Loop::Event @@ -1721,6 +1786,9 @@ The C module has a relatively high setup and callback invocation cost, but overall scores in on the third place. +C performs admirably well, about on par with C, even +when using its pure perl backend. + C's memory usage is quite a bit higher, but it features a faster callback invocation and overall ends up in the same class as C. However, Glib scales extremely badly, doubling the number of @@ -1807,12 +1875,14 @@ =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 + name sockets create request + EV 20000 69.01 11.16 + Perl 20000 73.32 35.87 + IOAsync 20000 157.00 98.14 epoll + IOAsync 20000 159.31 616.06 poll + Event 20000 212.62 257.32 + Glib 20000 651.16 1896.30 + POE 20000 349.67 12317.24 uses POE::Loop::Event =head3 Discussion @@ -1825,6 +1895,9 @@ Perl surprisingly comes second. It is much faster than the C-based event loops Event and Glib. +IO::Async performs very well when using its epoll backend, and still quite +good compared to Glib when using its pure perl backend. + 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 @@ -1902,14 +1975,15 @@ could be misinterpreted to make AnyEvent look bad. In fact, the benchmark simply compares IO::Lambda with POE, and IO::Lambda looks better (which shouldn't come as a surprise to anybody). As such, the benchmark is -fine, and shows that the AnyEvent backend from IO::Lambda isn't very -optimal. But how would AnyEvent compare when used without the extra +fine, and mostly shows that the AnyEvent backend from IO::Lambda isn't +very optimal. But how would AnyEvent compare when used without the extra baggage? To explore this, I wrote the equivalent benchmark for AnyEvent. The benchmark itself creates an echo-server, and then, for 500 times, connects to the echo server, sends a line, waits for the reply, and then creates the next connection. This is a rather bad benchmark, as it doesn't -test the efficiency of the framework, but it is a benchmark nevertheless. +test the efficiency of the framework or much non-blocking I/O, but it is a +benchmark nevertheless. name runtime Lambda/select 0.330 sec @@ -1925,28 +1999,32 @@ AnyEvent/EV/nb 0.068 sec +state machine 0.134 sec -The benchmark is also a bit unfair (my fault) - the IO::Lambda +The benchmark is also a bit unfair (my fault): the IO::Lambda/POE benchmarks actually make blocking connects and use 100% blocking I/O, defeating the purpose of an event-based solution. All of the newly written AnyEvent benchmarks use 100% non-blocking connects (using AnyEvent::Socket::tcp_connect and the asynchronous pure perl DNS -resolver), so AnyEvent is at a disadvantage here as non-blocking connects +resolver), so AnyEvent is at a disadvantage here, as non-blocking connects generally require a lot more bookkeeping and event handling than blocking connects (which involve a single syscall only). The last AnyEvent benchmark additionally uses L, which -offers similar expressive power as POE and IO::Lambda (using conventional -Perl syntax), which means both the echo server and the client are 100% -non-blocking w.r.t. I/O, further placing it at a disadvantage. - -As you can see, AnyEvent + EV even beats the hand-optimised "raw sockets -benchmark", while AnyEvent + its pure perl backend easily beats -IO::Lambda and POE. +offers similar expressive power as POE and IO::Lambda, using conventional +Perl syntax. This means that both the echo server and the client are 100% +non-blocking, further placing it at a disadvantage. + +As you can see, the AnyEvent + EV combination even beats the +hand-optimised "raw sockets benchmark", while AnyEvent + its pure perl +backend easily beats IO::Lambda and POE. And even the 100% non-blocking version written using the high-level (and -slow :) L abstraction beats both POE and IO::Lambda, -even thought it does all of DNS, tcp-connect and socket I/O in a -non-blocking way. +slow :) L abstraction beats both POE and IO::Lambda by a +large margin, even though it does all of DNS, tcp-connect and socket I/O +in a non-blocking way. + +The two AnyEvent benchmarks programs can be found as F and +F in the AnyEvent distribution, the remaining benchmarks are +part of the IO::lambda distribution and were used without any changes. =head1 SIGNALS @@ -1961,6 +2039,9 @@ emulation for event loops that do not support them natively. Also, some event loops install a similar handler. +If, when AnyEvent is loaded, SIGCHLD is set to IGNORE, then AnyEvent will +reset it to default, to avoid losing child exit statuses. + =item SIGPIPE A no-op handler is installed for C when C<$SIG{PIPE}> is C @@ -1981,10 +2062,12 @@ =cut +undef $SIG{CHLD} + if $SIG{CHLD} eq 'IGNORE'; + $SIG{PIPE} = sub { } unless defined $SIG{PIPE}; - =head1 FORK Most event libraries are not fork-safe. The ones who are usually are @@ -2016,6 +2099,10 @@ probably even less useful to an attacker than PERL_ANYEVENT_MODEL), and $ENV{PERL_ANYEVENT_STRICT}. +Note that AnyEvent will remove I environment variables starting with +C from C<%ENV> when it is loaded while taint mode is +enabled. + =head1 BUGS