]> err.no Git - varnish/commitdiff
Add an epoll()-based acceptor for Linux 2.6. Simple empirical tests indicate
authordes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 9 Aug 2006 14:49:49 +0000 (14:49 +0000)
committerdes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 9 Aug 2006 14:49:49 +0000 (14:49 +0000)
that epoll() performs significantly better than poll() (less CPU usage).

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@780 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache_acceptor.c
varnish-cache/configure.ac

index b09627d37baca6c734eec1cce8b808ea2e32ffd5..7889214338eae33d204db2060b4a2bfa227d6668 100644 (file)
@@ -7,10 +7,13 @@
  */
 
 #undef ACCEPTOR_USE_KQUEUE
+#undef ACCEPTOR_USE_EPOLL
 #undef ACCEPTOR_USE_POLL
 
 #if defined(HAVE_KQUEUE)
 #define ACCEPTOR_USE_KQUEUE 1
+#elif defined(HAVE_EPOLL_CTL)
+#define ACCEPTOR_USE_EPOLL 1
 #elif defined(HAVE_POLL)
 #define ACCEPTOR_USE_POLL 1
 #else
@@ -260,6 +263,125 @@ vca_return_session(struct sess *sp)
 
 #endif /* ACCEPTOR_USE_POLL */
 /*====================================================================*/
+#ifdef ACCEPTOR_USE_EPOLL
+
+#include <sys/epoll.h>
+
+static int epfd = -1;
+static int pipes[2];
+
+static TAILQ_HEAD(,sess) sesshead = TAILQ_HEAD_INITIALIZER(sesshead);
+
+static void
+vca_add(int fd, void *data)
+{
+       struct epoll_event ev = { EPOLLIN | EPOLLPRI, { data } };
+       AZ(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev));
+}
+
+static void
+vca_del(int fd)
+{
+       AZ(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL));
+}
+
+static void
+vca_rcvhdev(struct sess *sp)
+{
+
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+       clock_gettime(CLOCK_MONOTONIC, &sp->t_idle);
+       TAILQ_INSERT_TAIL(&sesshead, sp, list);
+       vca_add(sp->fd, sp);
+}
+
+static void
+accept_f(int fd)
+{
+       struct sess *sp;
+
+       sp = vca_accept_sess(fd);
+       if (sp == NULL)
+               return;
+       http_RecvPrep(sp->http);
+       vca_rcvhdev(sp);
+}
+
+static void *
+vca_main(void *arg)
+{
+       struct epoll_event ev;
+       struct timespec t;
+       struct sess *sp, *sp2;
+       int i;
+
+       (void)arg;
+
+       epfd = epoll_create(16);
+       assert(epfd >= 0);
+
+       AZ(pipe(pipes));
+       vca_add(pipes[0], pipes);
+
+       if (heritage.socket >= 0)
+               vca_add(heritage.socket, accept_f);
+
+       while (1) {
+               if (epoll_wait(epfd, &ev, 1, 5000) > 0) {
+                       if (ev.data.ptr == pipes) {
+                               i = read(pipes[0], &sp, sizeof sp);
+                               assert(i == sizeof sp);
+                               CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+                               if (http_RecvPrepAgain(sp->http))
+                                       vca_handover(sp, 0);
+                               else
+                                       vca_rcvhdev(sp);
+                       } else if (ev.data.ptr == accept_f) {
+                               accept_f(heritage.socket);
+                       } else {
+                               CAST_OBJ_NOTNULL(sp, ev.data.ptr, SESS_MAGIC);
+                               i = http_RecvSome(sp->fd, sp->http);
+                               if (i != -1) {
+                                       TAILQ_REMOVE(&sesshead, sp, list);
+                                       vca_del(sp->fd);
+                                       vca_handover(sp, i);
+                               }
+                       }
+               }
+               /* check for timeouts */
+               clock_gettime(CLOCK_MONOTONIC, &t);
+               TAILQ_FOREACH_SAFE(sp, &sesshead, list, sp2) {
+                       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+                       if (sp->t_idle.tv_sec + 5 < t.tv_sec) {
+                               TAILQ_REMOVE(&sesshead, sp, list);
+                               vca_del(sp->fd);
+                               vca_close_session(sp, "timeout");
+                               vca_return_session(sp);
+                               continue;
+                       }
+               }
+       }
+
+       INCOMPL();
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+vca_return_session(struct sess *sp)
+{
+
+       if (sp->fd < 0) {
+               SES_Delete(sp);
+               return;
+       }
+       (void)clock_gettime(CLOCK_REALTIME, &sp->t_open);
+       VSL(SLT_SessionReuse, sp->fd, "%s %s", sp->addr, sp->port);
+       assert(sizeof sp == write(pipes[1], &sp, sizeof sp));
+}
+
+#endif /* ACCEPTOR_USE_EPOLL */
+/*====================================================================*/
 #ifdef ACCEPTOR_USE_KQUEUE
 
 #include <sys/event.h>
index 172c37d27ded1bda250e979005ed57504b7336e7..925eb4c7d5cd9488c02cca3c0978096e61011942 100644 (file)
@@ -90,6 +90,7 @@ AM_CONDITIONAL(NEED_LIBMD, test x$need_libmd = xyes)
 
 # Check which mechanism to use for the acceptor
 AC_CHECK_FUNCS([kqueue])
+AC_CHECK_FUNCS([epoll_ctl])
 AC_CHECK_FUNCS([poll])
 
 AC_CONFIG_FILES([