--- libev/ev.pod 2007/12/07 19:15:39 1.69 +++ libev/ev.pod 2007/12/22 16:21:25 1.102 @@ -55,7 +55,7 @@ time: L. Libev is an event loop: you register interest in certain events (such as a -file descriptor being readable or a timeout occuring), and it will manage +file descriptor being readable or a timeout occurring), and it will manage these event sources and provide your program with events. To do this, it must take more or less complete control over your process @@ -100,7 +100,9 @@ the beginning of 1970, details are complicated, don't ask). This type is called C, which is what you should use too. It usually aliases to the C type in C, and when you need to do any calculations on -it, you should treat it as such. +it, you should treat it as some floatingpoint value. Unlike the name +component C might indicate, it is also used for time differences +throughout libev. =head1 GLOBAL FUNCTIONS @@ -115,18 +117,27 @@ C function is usually faster and also often returns the timestamp you actually want to know. +=item ev_sleep (ev_tstamp interval) + +Sleep for the given interval: The current thread will be blocked until +either it is interrupted or the given time interval has passed. Basically +this is a subsecond-resolution C. + =item int ev_version_major () =item int ev_version_minor () -You can find out the major and minor version numbers of the library +You can find out the major and minor ABI version numbers of the library you linked against by calling the functions C and C. If you want, you can compare against the global symbols C and C, which specify the version of the library your program was compiled against. +These version numbers refer to the ABI version of the library, not the +release version. + Usually, it's a good idea to terminate if the major versions mismatch, -as this indicates an incompatible change. Minor versions are usually +as this indicates an incompatible change. Minor versions are usually compatible to older versions, so a larger minor version alone is usually not a problem. @@ -297,67 +308,111 @@ This is your standard select(2) backend. Not I standard, as libev tries to roll its own fd_set with no limits on the number of fds, but if that fails, expect a fairly low limit on the number of fds when -using this backend. It doesn't scale too well (O(highest_fd)), but its usually -the fastest backend for a low number of fds. +using this backend. It doesn't scale too well (O(highest_fd)), but its +usually the fastest backend for a low number of (low-numbered :) fds. + +To get good performance out of this backend you need a high amount of +parallelity (most of the file descriptors should be busy). If you are +writing a server, you should C in a loop to accept as many +connections as possible during one iteration. You might also want to have +a look at C to increase the amount of +readyness notifications you get per iteration. =item C (value 2, poll backend, available everywhere except on windows) -And this is your standard poll(2) backend. It's more complicated than -select, but handles sparse fds better and has no artificial limit on the -number of fds you can use (except it will slow down considerably with a -lot of inactive fds). It scales similarly to select, i.e. O(total_fds). +And this is your standard poll(2) backend. It's more complicated +than select, but handles sparse fds better and has no artificial +limit on the number of fds you can use (except it will slow down +considerably with a lot of inactive fds). It scales similarly to select, +i.e. O(total_fds). See the entry for C, above, for +performance tips. =item C (value 4, Linux) For few fds, this backend is a bit little slower than poll and select, -but it scales phenomenally better. While poll and select usually scale like -O(total_fds) where n is the total number of fds (or the highest fd), epoll scales -either O(1) or O(active_fds). +but it scales phenomenally better. While poll and select usually scale +like O(total_fds) where n is the total number of fds (or the highest fd), +epoll scales either O(1) or O(active_fds). The epoll design has a number +of shortcomings, such as silently dropping events in some hard-to-detect +cases and rewiring a syscall per fd change, no fork support and bad +support for dup. -While stopping and starting an I/O watcher in the same iteration will -result in some caching, there is still a syscall per such incident +While stopping, setting and starting an I/O watcher in the same iteration +will result in some caching, there is still a syscall per such incident (because the fd could point to a different file description now), so its -best to avoid that. Also, dup()ed file descriptors might not work very -well if you register events for both fds. +best to avoid that. Also, C'ed file descriptors might not work +very well if you register events for both fds. Please note that epoll sometimes generates spurious notifications, so you need to use non-blocking I/O or other means to avoid blocking when no data (or space) is available. +Best performance from this backend is achieved by not unregistering all +watchers for a file descriptor until it has been closed, if possible, i.e. +keep at least one watcher active per fd at all times. + +While nominally embeddeble in other event loops, this feature is broken in +all kernel versions tested so far. + =item C (value 8, most BSD clones) Kqueue deserves special mention, as at the time of this writing, it -was broken on all BSDs except NetBSD (usually it doesn't work with -anything but sockets and pipes, except on Darwin, where of course its -completely useless). For this reason its not being "autodetected" +was broken on all BSDs except NetBSD (usually it doesn't work reliably +with anything but sockets and pipes, except on Darwin, where of course +it's completely useless). For this reason it's not being "autodetected" unless you explicitly specify it explicitly in the flags (i.e. using -C). +C) or libev was compiled on a known-to-be-good (-enough) +system like NetBSD. + +You still can embed kqueue into a normal poll or select backend and use it +only for sockets (after having made sure that sockets work with kqueue on +the target platform). See C watchers for more info. It scales in the same way as the epoll backend, but the interface to the kernel is more efficient (which says nothing about its actual speed, of -course). While starting and stopping an I/O watcher does not cause an -extra syscall as with epoll, it still adds up to four event changes per -incident, so its best to avoid that. +course). While stopping, setting and starting an I/O watcher does never +cause an extra syscall as with C, it still adds up to +two event changes per incident, support for C is very bad and it +drops fds silently in similarly hard-to-detect cases. + +This backend usually performs well under most conditions. + +While nominally embeddable in other event loops, this doesn't work +everywhere, so you might need to test for this. And since it is broken +almost everywhere, you should only use it when you have a lot of sockets +(for which it usually works), by embedding it into another event loop +(e.g. C or C) and using it only for +sockets. =item C (value 16, Solaris 8) -This is not implemented yet (and might never be). +This is not implemented yet (and might never be, unless you send me an +implementation). According to reports, C only supports sockets +and is not embeddable, which would limit the usefulness of this backend +immensely. =item C (value 32, Solaris 10) -This uses the Solaris 10 port mechanism. As with everything on Solaris, +This uses the Solaris 10 event port mechanism. As with everything on Solaris, it's really slow, but it still scales very well (O(active_fds)). -Please note that solaris ports can result in a lot of spurious +Please note that solaris event ports can deliver a lot of spurious notifications, so you need to use non-blocking I/O or other means to avoid blocking when no data (or space) is available. +While this backend scales well, it requires one system call per active +file descriptor per loop iteration. For small and medium numbers of file +descriptors a "slow" C or C backend +might perform better. + =item C Try all backends (even potentially broken ones that wouldn't be tried with C). Since this is a mask, you can do stuff such as C. +It is definitely not recommended to use this flag. + =back If one or more of these are ored into the flags value, then only these @@ -401,9 +456,18 @@ sense, so e.g. C might still return true. It is your responsibility to either stop all watchers cleanly yoursef I calling this function, or cope with the fact afterwards (which is usually -the easiest thing, youc na just ignore the watchers and/or C them +the easiest thing, you can just ignore the watchers and/or C them for example). +Note that certain global state, such as signal state, will not be freed by +this function, and related watchers (such as signal and child watchers) +would need to be stopped manually. + +In general it is not advisable to call this function except in the +rare occasion where you really need to free e.g. the signal handling +pipe fds. If you need dynamically allocated loops it is better to use +C and C). + =item ev_loop_destroy (loop) Like C, but destroys an event loop created by an @@ -457,7 +521,7 @@ received events and started processing them. This timestamp does not change as long as callbacks are being processed, and this is also the base time used for relative timers. You can treat it as the timestamp of the -event occuring (or more correctly, libev finding out about it). +event occurring (or more correctly, libev finding out about it). =item ev_loop (loop, int flags) @@ -488,8 +552,9 @@ Here are the gory details of what C does: + - Before the first iteration, call any pending watchers. * If there are no active watchers (reference count is zero), return. - - Queue prepare watchers and then call all outstanding watchers. + - Queue all prepare watchers and then call all outstanding watchers. - If we have been forked, recreate the kernel state. - Update the kernel state with all outstanding changes. - Update the "event loop time". @@ -550,6 +615,42 @@ ev_ref (loop); ev_signal_stop (loop, &exitsig); +=item ev_set_io_collect_interval (loop, ev_tstamp interval) + +=item ev_set_timeout_collect_interval (loop, ev_tstamp interval) + +These advanced functions influence the time that libev will spend waiting +for events. Both are by default C<0>, meaning that libev will try to +invoke timer/periodic callbacks and I/O callbacks with minimum latency. + +Setting these to a higher value (the C I be >= C<0>) +allows libev to delay invocation of I/O and timer/periodic callbacks to +increase efficiency of loop iterations. + +The background is that sometimes your program runs just fast enough to +handle one (or very few) event(s) per loop iteration. While this makes +the program responsive, it also wastes a lot of CPU time to poll for new +events, especially with backends like C. =item EV_USE_SELECT @@ -2215,11 +2555,36 @@ Can be used to change the callback member declaration in each watcher, and the way callbacks are invoked and set. Must expand to a struct member -definition and a statement, respectively. See the F header file for +definition and a statement, respectively. See the F header file for their default definitions. One possible use for overriding these is to avoid the C as first argument in all cases, or to use method calls instead of plain function calls in C++. +=head2 EXPORTED API SYMBOLS + +If you need to re-export the API (e.g. via a dll) and you need a list of +exported symbols, you can use the provided F files which list +all public symbols, one per line: + + Symbols.ev for libev proper + Symbols.event for the libevent emulation + +This can also be used to rename all public symbols to avoid clashes with +multiple versions of libev linked together (which is obviously bad in +itself, but sometimes it is inconvinient to avoid this). + +A sed command like this will create wrapper C<#define>'s that you need to +include before including F: + + wrap.h + +This would create a file F which essentially looks like this: + + #define ev_backend myprefix_ev_backend + #define ev_check_start myprefix_ev_check_start + #define ev_check_stop myprefix_ev_check_stop + ... + =head2 EXAMPLES For a real-world example of a program the includes libev @@ -2257,6 +2622,12 @@ libev will be explained. For complexity discussions about backends see the documentation for C. +All of the following are about amortised time: If an array needs to be +extended, libev needs to realloc and move the whole array, but this +happens asymptotically never with higher number of elements, so O(1) might +mean it might do a lengthy realloc operation in rare cases, but on average +it is much faster and asymptotically approaches constant time. + =over 4 =item Starting and stopping timer/periodic watchers: O(log skipped_other_timers) @@ -2272,11 +2643,7 @@ =item Starting io/check/prepare/idle/signal/child watchers: O(1) -These just add the watcher into an array or at the head of a list. If -the array needs to be extended libev needs to realloc and move the whole -array, but this happen asymptotically less and less with more watchers, -thus amortised O(1). - +These just add the watcher into an array or at the head of a list. =item Stopping check/prepare/idle watchers: O(1) =item Stopping an io/signal/child watcher: O(number_of_watchers_for_this_(fd/signal/pid % EV_PID_HASHSIZE))