r780 - in trunk/varnish-cache: . bin/varnishd

des at projects.linpro.no des at projects.linpro.no
Wed Aug 9 16:49:49 CEST 2006


Author: des
Date: 2006-08-09 16:49:49 +0200 (Wed, 09 Aug 2006)
New Revision: 780

Modified:
   trunk/varnish-cache/bin/varnishd/cache_acceptor.c
   trunk/varnish-cache/configure.ac
Log:
Add an epoll()-based acceptor for Linux 2.6.  Simple empirical tests indicate
that epoll() performs significantly better than poll() (less CPU usage).

Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_acceptor.c	2006-08-09 12:38:11 UTC (rev 779)
+++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c	2006-08-09 14:49:49 UTC (rev 780)
@@ -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 @@
 
 #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>

Modified: trunk/varnish-cache/configure.ac
===================================================================
--- trunk/varnish-cache/configure.ac	2006-08-09 12:38:11 UTC (rev 779)
+++ trunk/varnish-cache/configure.ac	2006-08-09 14:49:49 UTC (rev 780)
@@ -90,6 +90,7 @@
 
 # Check which mechanism to use for the acceptor
 AC_CHECK_FUNCS([kqueue])
+AC_CHECK_FUNCS([epoll_ctl])
 AC_CHECK_FUNCS([poll])
 
 AC_CONFIG_FILES([




More information about the varnish-commit mailing list