[master] 255f02c Move inserts into the binheap into the expiry-thread.

Poul-Henning Kamp phk at varnish-cache.org
Tue Oct 8 13:55:55 CEST 2013


commit 255f02cfcfb50b24efab29616208bb22459bd271
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Oct 8 11:55:01 2013 +0000

    Move inserts into the binheap into the expiry-thread.
    
    This should make object creation faster.
    
    As a sideeffect, we loose the $expiry_sleep parameter:  Now we always
    sleep optimally.

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 0bd75c9..5f68e22 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -434,7 +434,7 @@ struct objcore {
 	unsigned		flags;
 #define OC_F_BUSY		(1<<1)
 #define OC_F_PASS		(1<<2)
-// #define OC_F_LRUDONTMOVE	(1<<4)
+#define OC_F_OFFLRU		(1<<4)
 #define OC_F_PRIV		(1<<5)		/* Stevedore private flag */
 #define OC_F_LURK		(3<<6)		/* Ban-lurker-color */
 #define OC_F_PRIVATE		(1<<8)
diff --git a/bin/varnishd/cache/cache_expire.c b/bin/varnishd/cache/cache_expire.c
index 00ad4a4..a340af9 100644
--- a/bin/varnishd/cache/cache_expire.c
+++ b/bin/varnishd/cache/cache_expire.c
@@ -54,6 +54,7 @@ struct exp_priv {
 	struct lock			mtx;
 	VTAILQ_HEAD(,objcore)		inbox;
 	struct binheap			*heap;
+	pthread_cond_t			condvar;
 };
 
 static struct exp_priv *exphdl;
@@ -111,22 +112,6 @@ update_object_when(const struct object *o)
 	return (1);
 }
 
-/*--------------------------------------------------------------------*/
-
-static void
-exp_insert(struct objcore *oc, struct lru *lru)
-{
-	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
-	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
-
-	Lck_AssertHeld(&lru->mtx);
-	Lck_AssertHeld(&exphdl->mtx);
-	assert(oc->timer_idx == BINHEAP_NOIDX);
-	binheap_insert(exphdl->heap, oc);
-	assert(oc->timer_idx != BINHEAP_NOIDX);
-	VTAILQ_INSERT_TAIL(&lru->lru_head, oc, lru_list);
-}
-
 /*--------------------------------------------------------------------
  * Object has been added to cache, record in lru & binheap.
  *
@@ -141,11 +126,15 @@ EXP_Inject(struct objcore *oc, struct lru *lru, double when)
 	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
 
 	Lck_Lock(&lru->mtx);
+	lru->n_objcore++;
+	Lck_Unlock(&lru->mtx);
+
 	Lck_Lock(&exphdl->mtx);
 	oc->timer_when = when;
-	exp_insert(oc, lru);
+	oc->flags |= OC_F_OFFLRU;
+	VTAILQ_INSERT_TAIL(&exphdl->inbox, oc, lru_list);
+	AZ(pthread_cond_signal(&exphdl->condvar));
 	Lck_Unlock(&exphdl->mtx);
-	Lck_Unlock(&lru->mtx);
 }
 
 /*--------------------------------------------------------------------
@@ -172,11 +161,16 @@ EXP_Insert(const struct object *o, double now)
 	lru = oc_getlru(oc);
 	CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
 	Lck_Lock(&lru->mtx);
+	lru->n_objcore++;
+	Lck_Unlock(&lru->mtx);
+
 	Lck_Lock(&exphdl->mtx);
 	(void)update_object_when(o);
-	exp_insert(oc, lru);
+	oc->flags |= OC_F_OFFLRU;
+	VTAILQ_INSERT_TAIL(&exphdl->inbox, oc, lru_list);
+	AZ(pthread_cond_signal(&exphdl->condvar));
 	Lck_Unlock(&exphdl->mtx);
-	Lck_Unlock(&lru->mtx);
+
 	oc_updatemeta(oc);
 }
 
@@ -214,7 +208,9 @@ EXP_Touch(struct objcore *oc)
 	if (Lck_Trylock(&lru->mtx))
 		return (0);
 
-	if (oc->timer_idx != BINHEAP_NOIDX) {
+	if (oc->flags & OC_F_OFFLRU) {
+		/* Cannot move it while it's in the inbox */
+	} else if (oc->timer_idx != BINHEAP_NOIDX) {
 		VTAILQ_REMOVE(&lru->lru_head, oc, lru_list);
 		VTAILQ_INSERT_TAIL(&lru->lru_head, oc, lru_list);
 		VSC_C_main->n_lru_moved++;
@@ -254,6 +250,7 @@ EXP_Rearm(const struct object *o)
 		assert(oc->timer_idx != BINHEAP_NOIDX);
 		binheap_reorder(exphdl->heap, oc->timer_idx);
 		assert(oc->timer_idx != BINHEAP_NOIDX);
+		AZ(pthread_cond_signal(&exphdl->condvar)); // XXX
 	}
 	Lck_Unlock(&exphdl->mtx);
 	Lck_Unlock(&lru->mtx);
@@ -274,24 +271,55 @@ exp_timer(struct worker *wrk, void *priv)
 	struct object *o;
 	struct vsl_log vsl;
 	struct exp_priv *ep;
-
+	struct timespec ts;
+	int idle;
 
 	CAST_OBJ_NOTNULL(ep, priv, EXP_PRIV_MAGIC);
 	VSL_Setup(&vsl, NULL, 0);
 	t = VTIM_real();
 	oc = NULL;
+	idle = 0;
 	while (1) {
-		if (oc == NULL) {
+		Lck_Lock(&ep->mtx);
+
+		if (idle) {
 			VSL_Flush(&vsl, 0);
 			WRK_SumStat(wrk);
-			VTIM_sleep(cache_param->expiry_sleep);
+			oc = binheap_root(ep->heap);
+			if (oc != NULL && oc->timer_when > 0.0) {
+				ts.tv_nsec = modf(oc->timer_when, &t) * 1e9;
+				ts.tv_sec = t;
+				(void)Lck_CondWait(&ep->condvar, &ep->mtx, &ts);
+			} else if (oc == NULL) {
+				(void)Lck_CondWait(&ep->condvar, &ep->mtx,NULL);
+			} else {
+				/* We're behind, don't sleep */
+			}
 			t = VTIM_real();
 		}
 
-		Lck_Lock(&exphdl->mtx);
-		oc = binheap_root(exphdl->heap);
+		oc = VTAILQ_FIRST(&ep->inbox);
+		if (oc != NULL) {
+			VTAILQ_REMOVE(&ep->inbox, oc, lru_list);
+			assert(oc->timer_idx == BINHEAP_NOIDX);
+			binheap_insert(exphdl->heap, oc);
+			assert(oc->timer_idx != BINHEAP_NOIDX);
+			Lck_Unlock(&ep->mtx);
+
+			lru = oc_getlru(oc);
+			Lck_Lock(&lru->mtx);
+			VTAILQ_INSERT_TAIL(&lru->lru_head, oc, lru_list);
+			oc->flags &= ~OC_F_OFFLRU;
+			oc->last_lru = t;
+			Lck_Unlock(&lru->mtx);
+			idle = 0;
+			continue;
+		}
+
+		oc = binheap_root(ep->heap);
 		if (oc == NULL) {
-			Lck_Unlock(&exphdl->mtx);
+			Lck_Unlock(&ep->mtx);
+			idle = 1;
 			continue;
 		}
 		CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
@@ -303,22 +331,22 @@ exp_timer(struct worker *wrk, void *priv)
 		if (oc->timer_when > t)
 			t = VTIM_real();
 		if (oc->timer_when > t) {
-			Lck_Unlock(&exphdl->mtx);
-			oc = NULL;
+			Lck_Unlock(&ep->mtx);
+			idle = 1;
 			continue;
 		}
 
 		/* If the object is busy, we have to wait for it */
 		if (oc->flags & OC_F_BUSY) {
-			Lck_Unlock(&exphdl->mtx);
-			oc = NULL;
+			Lck_Unlock(&ep->mtx);
+			idle = 1;
 			continue;
 		}
 
 		/*
 		 * It's time...
-		 * Technically we should drop the exphdl->mtx, get the lru->mtx
-		 * get the exphdl->mtx again and then check that the oc is still
+		 * Technically we should drop the ep->mtx, get the lru->mtx
+		 * get the ep->mtx again and then check that the oc is still
 		 * on the binheap.  We take the shorter route and try to
 		 * get the lru->mtx and punt if we fail.
 		 */
@@ -326,21 +354,21 @@ exp_timer(struct worker *wrk, void *priv)
 		lru = oc_getlru(oc);
 		CHECK_OBJ_NOTNULL(lru, LRU_MAGIC);
 		if (Lck_Trylock(&lru->mtx)) {
-			Lck_Unlock(&exphdl->mtx);
-			oc = NULL;
+			Lck_Unlock(&ep->mtx);
+			idle = 1;
 			continue;
 		}
 
 		/* Remove from binheap */
 		assert(oc->timer_idx != BINHEAP_NOIDX);
-		binheap_delete(exphdl->heap, oc->timer_idx);
+		binheap_delete(ep->heap, oc->timer_idx);
 		assert(oc->timer_idx == BINHEAP_NOIDX);
 
 		/* And from LRU */
 		lru = oc_getlru(oc);
 		VTAILQ_REMOVE(&lru->lru_head, oc, lru_list);
 
-		Lck_Unlock(&exphdl->mtx);
+		Lck_Unlock(&ep->mtx);
 		Lck_Unlock(&lru->mtx);
 
 		VSC_C_main->n_expired++;
@@ -499,6 +527,7 @@ EXP_Init(void)
 	AN(ep);
 
 	Lck_New(&ep->mtx, lck_exp);
+	AZ(pthread_cond_init(&ep->condvar, NULL));
 	ep->heap = binheap_new(NULL, object_cmp, object_update);
 	AN(ep->heap);
 	VTAILQ_INIT(&ep->inbox);
diff --git a/bin/varnishd/common/params.h b/bin/varnishd/common/params.h
index f990354..4a16304 100644
--- a/bin/varnishd/common/params.h
+++ b/bin/varnishd/common/params.h
@@ -174,9 +174,6 @@ struct params {
 	/* Acceptable clockskew with backends */
 	unsigned		clock_skew;
 
-	/* Expiry pacer parameters */
-	double			expiry_sleep;
-
 	/* Acceptor pacer parameters */
 	double			acceptor_sleep_max;
 	double			acceptor_sleep_incr;
diff --git a/bin/varnishd/mgt/mgt_param_tbl.c b/bin/varnishd/mgt/mgt_param_tbl.c
index d2aca5c..f123661 100644
--- a/bin/varnishd/mgt/mgt_param_tbl.c
+++ b/bin/varnishd/mgt/mgt_param_tbl.c
@@ -173,11 +173,6 @@ const struct parspec mgt_parspec[] = {
 		" from first non-white-space character to double CRNL.",
 		0,
 		"2", "seconds" },
-	{ "expiry_sleep", tweak_timeout_double, &mgt_param.expiry_sleep, 0, 60,
-		"How long the expiry thread sleeps when there is nothing "
-		"for it to do.\n",
-		0,
-		"1", "seconds" },
 	{ "pipe_timeout", tweak_timeout, &mgt_param.pipe_timeout, 0, 0,
 		"Idle timeout for PIPE sessions. "
 		"If nothing have been received in either direction for "
diff --git a/bin/varnishtest/tests/r01140.vtc b/bin/varnishtest/tests/r01140.vtc
index e9d1eef..98abc61 100644
--- a/bin/varnishtest/tests/r01140.vtc
+++ b/bin/varnishtest/tests/r01140.vtc
@@ -18,7 +18,7 @@ server s1 {
 	txresp -bodylen 1025
 } -start
 
-varnish v1 -arg "-p expiry_sleep=0.01 -p nuke_limit=0 -p shortlived=0" \
+varnish v1 -arg "-p nuke_limit=0 -p shortlived=0" \
 	-storage "-smalloc,1m" -vcl+backend { 
 	sub vcl_backend_response {
 		set beresp.do_stream = false;



More information about the varnish-commit mailing list