stream: use kevent() information before accept()

Limit number of syscalls by using backlog length information provided by
kevent().
This commit is contained in:
Fedor Indutny 2013-02-08 14:48:52 +04:00
parent da33bba7c0
commit c15d4a7c62
6 changed files with 64 additions and 18 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -41,9 +41,29 @@
#include <pthread.h>
#include <signal.h>
#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

View File

@ -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) */
}

View File

@ -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);

View File

@ -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;