From 1e97f470d7efb51562242a32fa3145e02c19b030 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 10 Mar 2010 08:19:38 +0000 Subject: more minimal tuning, add truly minimal example --- Changes | 4 +++- ev.c | 63 ++++++++++++++++++++++++++++++++++++++++----------------------- ev.h | 27 +++++++++++++++++++++++++-- ev.pod | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 116 insertions(+), 27 deletions(-) diff --git a/Changes b/Changes index 57f6cb8..9997f15 100644 --- a/Changes +++ b/Changes @@ -1,8 +1,9 @@ Revision history for libev, a high-performance and full-featured event loop. +TODO: accept() documentation - ev_embed_stop did not correctly stop the watcher (very good testcase by Vladimir Timofeev). - - applied win32 fixes by Michael Lenaghan. + - applied win32 fixes by Michael Lenaghan (also James Mansion). - remove dependency on sys/queue.h on freebsd (patch by Vanilla Hsu). - configure now prepends -O3, not appends it, so one can still override it. @@ -14,6 +15,7 @@ Revision history for libev, a high-performance and full-featured event loop. - implement EV_AVOID_STDIO option. - do not use sscanf to parse linux version number (smaller, faster, no sscanf dependency). + - new EV_CHILD_ENABLE and EV_SIGNAL_ENABLE configurable settings. 3.9 Thu Dec 31 07:59:59 CET 2009 - signalfd is no longer used by default and has to be requested diff --git a/ev.c b/ev.c index d0a160a..2a66b60 100644 --- a/ev.c +++ b/ev.c @@ -209,12 +209,13 @@ extern "C" { #elif defined (MAX_SIG) # define EV_NSIG (MAX_SIG+1) #elif defined (SIGARRAYSIZE) -# define EV_NSIG SIGARRAYSIZE /* Assume ary[SIGARRAYSIZE] */ +# define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */ #elif defined (_sys_nsig) # define EV_NSIG (_sys_nsig) /* Solaris 2.5 */ #else # error "unable to find value for NSIG, please report" -/* to make it compile regardless, just remove the above line */ +/* to make it compile regardless, just remove the above line, */ +/* but consider reporting it, too! :) */ # define EV_NSIG 65 #endif @@ -994,7 +995,7 @@ fd_kill (EV_P_ int fd) } } -/* check whether the given fd is atcually valid, for error recovery */ +/* check whether the given fd is actually valid, for error recovery */ inline_size int fd_valid (int fd) { @@ -1046,6 +1047,20 @@ fd_rearm_all (EV_P) } } +/* used to prepare libev internal fd's */ +/* this is not fork-safe */ +inline_speed void +fd_intern (int fd) +{ +#ifdef _WIN32 + unsigned long arg = 1; + ioctlsocket (EV_FD_TO_WIN32_HANDLE (fd), FIONBIO, &arg); +#else + fcntl (fd, F_SETFD, FD_CLOEXEC); + fcntl (fd, F_SETFL, O_NONBLOCK); +#endif +} + /*****************************************************************************/ /* @@ -1207,26 +1222,14 @@ static ANSIG signals [EV_NSIG - 1]; /*****************************************************************************/ -/* used to prepare libev internal fd's */ -/* this is not fork-safe */ -inline_speed void -fd_intern (int fd) -{ -#ifdef _WIN32 - unsigned long arg = 1; - ioctlsocket (EV_FD_TO_WIN32_HANDLE (fd), FIONBIO, &arg); -#else - fcntl (fd, F_SETFD, FD_CLOEXEC); - fcntl (fd, F_SETFL, O_NONBLOCK); -#endif -} +#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE static void noinline evpipe_init (EV_P) { if (!ev_is_active (&pipe_w)) { -#if EV_USE_EVENTFD +# if EV_USE_EVENTFD evfd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC); if (evfd < 0 && errno == EINVAL) evfd = eventfd (0, 0); @@ -1238,7 +1241,7 @@ evpipe_init (EV_P) ev_io_set (&pipe_w, evfd, EV_READ); } else -#endif +# endif { while (pipe (evpipe)) ev_syserr ("(libev) error creating signal/async pipe"); @@ -1259,6 +1262,7 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag) if (!*flag) { int old_errno = errno; /* save errno because write might clobber it */ + char dummy; *flag = 1; @@ -1270,7 +1274,7 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag) } else #endif - write (evpipe [1], &old_errno, 1); + write (evpipe [1], &dummy, 1); errno = old_errno; } @@ -1381,12 +1385,13 @@ sigfdcb (EV_P_ ev_io *iow, int revents) } #endif +#endif + /*****************************************************************************/ +#if EV_CHILD_ENABLE static WL childs [EV_PID_HASHSIZE]; -#ifndef _WIN32 - static ev_signal childev; #ifndef WIFCONTINUED @@ -1664,8 +1669,10 @@ loop_init (EV_P_ unsigned int flags) ev_prepare_init (&pending_w, pendingcb); +#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE ev_init (&pipe_w, pipecb); ev_set_priority (&pipe_w, EV_MAXPRI); +#endif } } @@ -1925,8 +1932,10 @@ ev_loop_verify (EV_P) array_verify (EV_A_ (W *)checks, checkcnt); # if 0 +#if EV_CHILD_ENABLE for (w = (ev_child *)childs [chain & (EV_PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next) for (signum = EV_NSIG; signum--; ) if (signals [signum].pending) +#endif # endif #endif } @@ -1952,7 +1961,7 @@ ev_default_loop (unsigned int flags) if (ev_backend (EV_A)) { -#ifndef _WIN32 +#if EV_CHILD_ENABLE ev_signal_init (&childev, childcb, SIGCHLD); ev_set_priority (&childev, EV_MAXPRI); ev_signal_start (EV_A_ &childev); @@ -1975,7 +1984,7 @@ ev_default_destroy (void) ev_default_loop_ptr = 0; -#ifndef _WIN32 +#if EV_CHILD_ENABLE ev_ref (EV_A); /* child watcher */ ev_signal_stop (EV_A_ &childev); #endif @@ -2727,6 +2736,8 @@ ev_periodic_again (EV_P_ ev_periodic *w) # define SA_RESTART 0 #endif +#if EV_SIGNAL_ENABLE + void noinline ev_signal_start (EV_P_ ev_signal *w) { @@ -2842,6 +2853,10 @@ ev_signal_stop (EV_P_ ev_signal *w) EV_FREQUENT_CHECK; } +#endif + +#if EV_CHILD_ENABLE + void ev_child_start (EV_P_ ev_child *w) { @@ -2874,6 +2889,8 @@ ev_child_stop (EV_P_ ev_child *w) EV_FREQUENT_CHECK; } +#endif + #if EV_STAT_ENABLE # ifdef _WIN32 diff --git a/ev.h b/ev.h index 06ff8cc..661ff98 100644 --- a/ev.h +++ b/ev.h @@ -74,14 +74,26 @@ typedef double ev_tstamp; # define EV_FORK_ENABLE 1 #endif -#ifndef EV_EMBED_ENABLE -# define EV_EMBED_ENABLE 1 +#ifndef EV_SIGNAL_ENABLE +# define EV_SIGNAL_ENABLE 1 +#endif + +#ifndef EV_CHILD_ENABLE +# ifdef _WIN32 +# define EV_CHILD_ENABLE 0 +# else +# define EV_CHILD_ENABLE 1 +#endif #endif #ifndef EV_ASYNC_ENABLE # define EV_ASYNC_ENABLE 1 #endif +#ifndef EV_EMBED_ENABLE +# define EV_EMBED_ENABLE 1 +#endif + #ifndef EV_WALK_ENABLE # define EV_WALK_ENABLE 0 /* not yet */ #endif @@ -93,6 +105,11 @@ typedef double ev_tstamp; /*****************************************************************************/ +#if EV_CHILD_ENABLE && !EV_SIGNAL_ENABLE +# undef EV_SIGNAL_ENABLE +# define EV_SIGNAL_ENABLE 1 +#endif + #if EV_STAT_ENABLE # ifdef _WIN32 # include @@ -632,7 +649,9 @@ void ev_resume (EV_P); /* accepts any ev_watcher type */ void ev_feed_event (EV_P_ void *w, int revents); void ev_feed_fd_event (EV_P_ int fd, int revents); +#if EV_SIGNAL_ENABLE void ev_feed_signal_event (EV_P_ int signum); +#endif void ev_invoke (EV_P_ void *w, int revents); int ev_clear_pending (EV_P_ void *w); @@ -653,12 +672,16 @@ void ev_periodic_again (EV_P_ ev_periodic *w); #endif /* only supported in the default loop */ +#if EV_SIGNAL_ENABLE void ev_signal_start (EV_P_ ev_signal *w); void ev_signal_stop (EV_P_ ev_signal *w); +#endif /* only supported in the default loop */ +# if EV_CHILD_ENABLE void ev_child_start (EV_P_ ev_child *w); void ev_child_stop (EV_P_ ev_child *w); +# endif # if EV_STAT_ENABLE void ev_stat_start (EV_P_ ev_stat *w); diff --git a/ev.pod b/ev.pod index f13391d..8c586e7 100644 --- a/ev.pod +++ b/ev.pod @@ -3868,11 +3868,21 @@ defined to be C<0>, then they are not. If undefined or defined to be C<1>, then fork watchers are supported. If defined to be C<0>, then they are not. +=item EV_SIGNAL_ENABLE + +If undefined or defined to be C<1>, then signal watchers are supported. If +defined to be C<0>, then they are not. + =item EV_ASYNC_ENABLE If undefined or defined to be C<1>, then async watchers are supported. If defined to be C<0>, then they are not. +=item EV_CHILD_ENABLE + +If undefined or defined to be C<1> (and C<_WIN32> is not defined), then +child watchers are supported. If defined to be C<0>, then they are not. + =item EV_MINIMAL If you need to shave off some kilobytes of code at the expense of some @@ -3883,13 +3893,50 @@ the default 4-heap. You can save even more by disabling watcher types you do not need and setting C == C. Also, disabling C -(C<-DNDEBUG>) will usually reduce code size a lot. +(C<-DNDEBUG>) will usually reduce code size a lot. Disabling inotify, +eventfd and signalfd will further help, and disabling backends one doesn't +need (e.g. poll, epoll, kqueue, ports) will help further. Defining C to C<2> will additionally reduce the core API to provide a bare-bones event library. See C for details on what parts of the API are still available, and do not complain if this subset changes over time. +This example set of settings reduces the compiled size of libev from 24Kb +to 8Kb on my GNU/Linux amd64 system (and leaves little in - there is also +an effect on the amount of memory used). With an intelligent-enough linker +further unused functions might be left out as well automatically. + + // tuning and API changes + #define EV_MINIMAL 2 + #define EV_MULTIPLICITY 0 + #define EV_MINPRI 0 + #define EV_MAXPRI 0 + + // OS-specific backends + #define EV_USE_INOTIFY 0 + #define EV_USE_EVENTFD 0 + #define EV_USE_SIGNALFD 0 + #define EV_USE_REALTIME 0 + #define EV_USE_MONOTONIC 0 + #define EV_USE_CLOCK_SYSCALL 0 + + // disable all backends except select + #define EV_USE_POLL 0 + #define EV_USE_PORT 0 + #define EV_USE_KQUEUE 0 + #define EV_USE_EPOLL 0 + + // disable all watcher types that cna be disabled + #define EV_STAT_ENABLE 0 + #define EV_PERIODIC_ENABLE 0 + #define EV_IDLE_ENABLE 0 + #define EV_FORK_ENABLE 0 + #define EV_SIGNAL_ENABLE 0 + #define EV_CHILD_ENABLE 0 + #define EV_ASYNC_ENABLE 0 + #define EV_EMBED_ENABLE 0 + =item EV_AVOID_STDIO If this is set to C<1> at compiletime, then libev will avoid using stdio -- cgit v1.2.3