From c15d4a7c6250a44fdfa0c6efab3ebcad359abc7d Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Fri, 8 Feb 2013 14:48:52 +0400 Subject: [PATCH] stream: use kevent() information before accept() Limit number of syscalls by using backlog length information provided by kevent(). --- include/uv-private/uv-bsd.h | 6 ++++++ include/uv-private/uv-darwin.h | 6 ++++++ include/uv-private/uv-unix.h | 34 +++++++++++++++++++++------------- src/unix/core.c | 5 +++++ src/unix/kqueue.c | 10 ++++++---- src/unix/stream.c | 21 ++++++++++++++++++++- 6 files changed, 64 insertions(+), 18 deletions(-) diff --git a/include/uv-private/uv-bsd.h b/include/uv-private/uv-bsd.h index fc253aa8..2d72b3d7 100644 --- a/include/uv-private/uv-bsd.h +++ b/include/uv-private/uv-bsd.h @@ -25,4 +25,10 @@ #define UV_PLATFORM_FS_EVENT_FIELDS \ uv__io_t event_watcher; \ +#define UV_IO_PRIVATE_PLATFORM_FIELDS \ + int rcount; \ + int wcount; \ + +#define UV_HAVE_KQUEUE 1 + #endif /* UV_BSD_H */ diff --git a/include/uv-private/uv-darwin.h b/include/uv-private/uv-darwin.h index f11c12ae..e861cbab 100644 --- a/include/uv-private/uv-darwin.h +++ b/include/uv-private/uv-darwin.h @@ -30,6 +30,10 @@ # define UV_PLATFORM_SEM_T semaphore_t #endif +#define UV_IO_PRIVATE_PLATFORM_FIELDS \ + int rcount; \ + int wcount; \ + #define UV_PLATFORM_LOOP_FIELDS \ uv_thread_t cf_thread; \ void* cf_cb; \ @@ -52,4 +56,6 @@ #define UV_STREAM_PRIVATE_PLATFORM_FIELDS \ void* select; \ +#define UV_HAVE_KQUEUE 1 + #endif /* UV_DARWIN_H */ diff --git a/include/uv-private/uv-unix.h b/include/uv-private/uv-unix.h index 6d2efbe2..f76f6ac4 100644 --- a/include/uv-private/uv-unix.h +++ b/include/uv-private/uv-unix.h @@ -41,9 +41,29 @@ #include #include +#if defined(__linux__) +# include "uv-linux.h" +#elif defined(__sun) +# include "uv-sunos.h" +#elif defined(__APPLE__) +# include "uv-darwin.h" +#elif defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) +# include "uv-bsd.h" +#endif + struct uv__io_s; struct uv_loop_s; +#ifndef UV_IO_PRIVATE_PLATFORM_FIELDS +# define UV_IO_PRIVATE_PLATFORM_FIELDS /* empty */ +#endif + +#define UV_IO_PRIVATE_FIELDS \ + UV_IO_PRIVATE_PLATFORM_FIELDS \ + typedef void (*uv__io_cb)(struct uv_loop_s* loop, struct uv__io_s* w, unsigned int events); @@ -56,6 +76,7 @@ struct uv__io_s { unsigned int pevents; /* Pending event mask i.e. mask at next tick. */ unsigned int events; /* Current event mask. */ int fd; + UV_IO_PRIVATE_FIELDS }; struct uv__work { @@ -65,19 +86,6 @@ struct uv__work { ngx_queue_t wq; }; -#if defined(__linux__) -# include "uv-linux.h" -#elif defined(__sun) -# include "uv-sunos.h" -#elif defined(__APPLE__) -# include "uv-darwin.h" -#elif defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) -# include "uv-bsd.h" -#endif - #ifndef UV_PLATFORM_SEM_T # define UV_PLATFORM_SEM_T sem_t #endif diff --git a/src/unix/core.c b/src/unix/core.c index 6bf3f7b2..77b8e519 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -595,6 +595,11 @@ void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) { w->fd = fd; w->events = 0; w->pevents = 0; + +#if defined(UV_HAVE_KQUEUE) + w->rcount = 0; + w->wcount = 0; +#endif /* defined(UV_HAVE_KQUEUE) */ } diff --git a/src/unix/kqueue.c b/src/unix/kqueue.c index 2ab0854b..fa090709 100644 --- a/src/unix/kqueue.c +++ b/src/unix/kqueue.c @@ -197,9 +197,10 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { revents = 0; if (ev->filter == EVFILT_READ) { - if (w->events & UV__POLLIN) + if (w->events & UV__POLLIN) { revents |= UV__POLLIN; - else { + w->rcount = ev->data; + } else { /* TODO batch up */ struct kevent events[1]; EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); @@ -210,9 +211,10 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } if (ev->filter == EVFILT_WRITE) { - if (w->events & UV__POLLOUT) + if (w->events & UV__POLLOUT) { revents |= UV__POLLOUT; - else { + w->wcount = ev->data; + } else { /* TODO batch up */ struct kevent events[1]; EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); diff --git a/src/unix/stream.c b/src/unix/stream.c index fbe4bd11..00e451c5 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -484,6 +484,13 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) { } +#if defined(UV_HAVE_KQUEUE) +# define UV_DEC_BACKLOG(w) w->rcount--; +#else +# define UV_DEC_BACKLOG(w) /* no-op */ +#endif /* defined(UV_HAVE_KQUEUE) */ + + void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { static int use_emfile_trick = -1; uv_stream_t* stream; @@ -503,6 +510,10 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { */ while (uv__stream_fd(stream) != -1) { assert(stream->accepted_fd == -1); +#if defined(UV_HAVE_KQUEUE) + if (w->rcount <= 0) + return; +#endif /* defined(UV_HAVE_KQUEUE) */ fd = uv__accept(uv__stream_fd(stream)); if (fd == -1) { @@ -514,6 +525,7 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { return; /* Not an error. */ case ECONNABORTED: + UV_DEC_BACKLOG(w) continue; /* Ignore. */ case EMFILE: @@ -525,8 +537,10 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { if (use_emfile_trick) { SAVE_ERRNO(r = uv__emfile_trick(loop, uv__stream_fd(stream))); - if (r == 0) + if (r == 0) { + UV_DEC_BACKLOG(w) continue; + } } /* Fall through. */ @@ -538,6 +552,8 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { } } + UV_DEC_BACKLOG(w) + stream->accepted_fd = fd; stream->connection_cb(stream, 0); @@ -556,6 +572,9 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { } +#undef UV_DEC_BACKLOG + + int uv_accept(uv_stream_t* server, uv_stream_t* client) { uv_stream_t* streamServer; uv_stream_t* streamClient;