[master] e9b524b Add the mempool guard-thread

Poul-Henning Kamp phk at varnish-cache.org
Thu Dec 15 10:32:25 CET 2011


commit e9b524b71aca73e048dd38ea8238f323e8be9558
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Thu Dec 15 09:32:09 2011 +0000

    Add the mempool guard-thread

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index edfe75f..9601270 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -855,9 +855,7 @@ int Lck_CondWait(pthread_cond_t *cond, struct lock *lck, struct timespec *ts);
 /* cache_mempool.c */
 struct mempool * MPL_New(const char *name, struct lock *mtx,
     volatile struct poolparam *pp, volatile unsigned *cur_size);
-void *MPL_GetLocked(struct mempool *mpl, unsigned *size);
 void *MPL_Get(struct mempool *mpl, unsigned *size);
-void MPL_FreeLocked(struct mempool *mpl, void *item);
 void MPL_Free(struct mempool *mpl, void *item);
 
 
diff --git a/bin/varnishd/cache/cache_mempool.c b/bin/varnishd/cache/cache_mempool.c
index 6677c84..6f46a2a 100644
--- a/bin/varnishd/cache/cache_mempool.c
+++ b/bin/varnishd/cache/cache_mempool.c
@@ -35,6 +35,8 @@
 
 #include "cache.h"
 
+#include "vtim.h"
+
 struct memitem {
 	unsigned			magic;
 #define MEMITEM_MAGIC			0x42e55401
@@ -47,14 +49,114 @@ struct mempool {
 	unsigned			magic;
 #define MEMPOOL_MAGIC			0x37a75a8d
 	VTAILQ_HEAD(,memitem)		list;
+	VTAILQ_HEAD(,memitem)		surplus;
 	struct lock			*mtx;
 	struct lock			imtx;
 	const char			*name;
 	volatile struct poolparam	*param;
 	volatile unsigned		*cur_size;
 	struct VSC_C_mempool		*vsc;
+	unsigned			n_pool;
+	pthread_t			thread;
 };
 
+/*---------------------------------------------------------------------
+ */
+
+static struct memitem *
+mpl_alloc(const struct mempool *mpl)
+{
+	unsigned tsz;
+	struct memitem *mi;
+
+	CHECK_OBJ_NOTNULL(mpl, MEMPOOL_MAGIC);
+	tsz = *mpl->cur_size;
+	mi = calloc(sizeof *mi + tsz, 1);
+	AN(mi);
+	mi->magic = MEMITEM_MAGIC;
+	mi->size = tsz;
+	return (mi);
+}
+
+/*---------------------------------------------------------------------
+ * Pool-guard
+ *   Attempt to keep number of free items in pool inside bounds with
+ *   minimum locking activity.
+ */
+
+static void *
+mpl_guard(void *priv)
+{
+	struct mempool *mpl;
+	struct memitem *mi = NULL;
+	double mpl_slp __state_variable__(mpl_slp);
+
+	CAST_OBJ_NOTNULL(mpl, priv, MEMPOOL_MAGIC);
+	mpl_slp = 0.15;	// random
+	while (1) {
+		VTIM_sleep(mpl_slp);
+		mpl_slp = 0.814;	// random
+
+		if (mi != NULL && (mpl->n_pool > mpl->param->max_pool ||
+		    mi->size < *mpl->cur_size)) {
+			FREE_OBJ(mi);
+			mi = NULL;
+		}
+
+		if (mi == NULL && mpl->n_pool < mpl->param->min_pool)
+			mi = mpl_alloc(mpl);
+
+		if (mpl->n_pool < mpl->param->min_pool && mi != NULL) {
+			/* can do */
+		} else if (mpl->n_pool > mpl->param->max_pool && mi == NULL) {
+			/* can do */
+		} else if (!VTAILQ_EMPTY(&mpl->surplus)) {
+			/* can do */
+		} else {
+			continue;	/* cannot do */
+		}
+
+		mpl_slp = 0.314;
+
+		if (Lck_Trylock(mpl->mtx))
+			continue;
+
+		mpl_slp = .01;
+
+		if (mpl->n_pool < mpl->param->min_pool &&
+		    mi != NULL && mi->size >= *mpl->cur_size) {
+			CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC);
+			mpl->vsc->pool++;
+			mpl->n_pool++;
+			VTAILQ_INSERT_HEAD(&mpl->list, mi, list);
+			mi = NULL;
+		}
+		if (mpl->n_pool > mpl->param->max_pool && mi == NULL) {
+			mi = VTAILQ_FIRST(&mpl->list);
+			CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC);
+			mpl->vsc->pool--;
+			mpl->n_pool--;
+			VTAILQ_REMOVE(&mpl->list, mi, list);
+		}
+		if (mi == NULL) {
+			mi = VTAILQ_FIRST(&mpl->surplus);
+			if (mi != NULL) {
+				CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC);
+				VTAILQ_REMOVE(&mpl->surplus, mi, list);
+			}
+		}
+		Lck_Unlock(mpl->mtx);
+
+		if (mi != NULL) {
+			FREE_OBJ(mi);
+			mi = NULL;
+		}
+	}
+}
+
+/*---------------------------------------------------------------------
+ */
+
 struct mempool *
 MPL_New(const char *name,
 	struct lock *mtx,
@@ -70,6 +172,7 @@ MPL_New(const char *name,
 	mpl->cur_size = cur_size;
 	mpl->mtx = mtx;
 	VTAILQ_INIT(&mpl->list);
+	VTAILQ_INIT(&mpl->surplus);
 	Lck_New(&mpl->imtx, lck_mempool);
 	if (mpl->mtx == NULL)
 		mpl->mtx = &mpl->imtx;
@@ -77,88 +180,77 @@ MPL_New(const char *name,
 	mpl->vsc = VSM_Alloc(sizeof *mpl->vsc,
 	    VSC_CLASS, VSC_TYPE_MEMPOOL, name);
 	AN(mpl->vsc);
+	AZ(pthread_create(&mpl->thread, NULL, mpl_guard, mpl));
 	return (mpl);
 }
 
 void *
-MPL_GetLocked(struct mempool *mpl, unsigned *size)
+MPL_Get(struct mempool *mpl, unsigned *size)
 {
 	struct memitem *mi;
-	unsigned tsz;
 
 	CHECK_OBJ_NOTNULL(mpl, MEMPOOL_MAGIC);
-	Lck_AssertHeld(mpl->mtx);
+
+	Lck_Lock(mpl->mtx);
 
 	mpl->vsc->allocs++;
 	mpl->vsc->live++;
+
 	do {
 		mi = VTAILQ_FIRST(&mpl->list);
 		if (mi == NULL)
 			break;
 		mpl->vsc->pool--;
+		mpl->n_pool--;
 		CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC);
 		VTAILQ_REMOVE(&mpl->list, mi, list);
 		if (mi->size < *mpl->cur_size) {
 			mpl->vsc->toosmall++;
-			FREE_OBJ(mi);
+			VTAILQ_INSERT_HEAD(&mpl->surplus, mi, list);
 			mi = NULL;
 		} else {
 			mpl->vsc->recycle++;
 		}
 	} while (mi == NULL);
-	if (mi == NULL) {
-		tsz = *mpl->cur_size;
-		mi = calloc(sizeof *mi + tsz, 1);
-		AN(mi);
-		mi->magic = MEMITEM_MAGIC;
-		mi->size = tsz;
-	}
+
+	Lck_Unlock(mpl->mtx);
+
+	if (mi == NULL)
+		mi = mpl_alloc(mpl);
 	if (size != NULL)
 		*size = mi->size;
-	return (&mi->payload);
+
+	/* Throw away sizeof info for FlexeLint: */
+	return ((void*)(uintptr_t)&mi->payload);
 }
 
 void
-MPL_FreeLocked(struct mempool *mpl, void *item)
+MPL_Free(struct mempool *mpl, void *item)
 {
 	struct memitem *mi;
 
 	CHECK_OBJ_NOTNULL(mpl, MEMPOOL_MAGIC);
-	Lck_AssertHeld(mpl->mtx);
-
-	mpl->vsc->frees++;
-	mpl->vsc->live--;
 
 	mi = (void*)((uintptr_t)item - offsetof(struct memitem, payload));
 	CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC);
+	memset(item, 0, mi->size);
+
+	Lck_Lock(mpl->mtx);
+
+	mpl->vsc->frees++;
+	mpl->vsc->live--;
 
 	if (mi->size < *mpl->cur_size) {
 		mpl->vsc->toosmall++;
-		FREE_OBJ(mi);
+		VTAILQ_INSERT_HEAD(&mpl->surplus, mi, list);
+	} else if (mpl->n_pool >= mpl->param->max_pool) {
+		mpl->vsc->surplus++;
+		VTAILQ_INSERT_HEAD(&mpl->surplus, mi, list);
 	} else {
 		mpl->vsc->pool++;
-		memset(item, 0, mi->size);
+		mpl->n_pool++;
 		VTAILQ_INSERT_HEAD(&mpl->list, mi, list);
 	}
-}
-
-void *
-MPL_Get(struct mempool *mpl, unsigned *size)
-{
-	void *p;
-
-	CHECK_OBJ_NOTNULL(mpl, MEMPOOL_MAGIC);
-	Lck_Lock(mpl->mtx);
-	p = MPL_GetLocked(mpl, size);
-	Lck_Unlock(mpl->mtx);
-	return (p);
-}
 
-void
-MPL_Free(struct mempool *mpl, void *item)
-{
-	CHECK_OBJ_NOTNULL(mpl, MEMPOOL_MAGIC);
-	Lck_Lock(mpl->mtx);
-	MPL_FreeLocked(mpl, item);
 	Lck_Unlock(mpl->mtx);
 }
diff --git a/bin/varnishd/mgt/mgt_param.c b/bin/varnishd/mgt/mgt_param.c
index 6faf0c5..1935344 100644
--- a/bin/varnishd/mgt/mgt_param.c
+++ b/bin/varnishd/mgt/mgt_param.c
@@ -632,7 +632,6 @@ tweak_poolparam(struct cli *cli, const struct parspec *par, const char *arg)
 			}
 			*pp = px;
 		} while(0);
-		
 	}
 }
 
diff --git a/include/tbl/vsc_fields.h b/include/tbl/vsc_fields.h
index cc72903..58f4d88 100644
--- a/include/tbl/vsc_fields.h
+++ b/include/tbl/vsc_fields.h
@@ -116,5 +116,6 @@ VSC_F(pool,			uint64_t, 0, 'g', "In Pool", "")
 VSC_F(recycle,			uint64_t, 0, 'g', "Recycled from pool", "")
 VSC_F(timeout,			uint64_t, 0, 'g', "Timed out from pool", "")
 VSC_F(toosmall,			uint64_t, 0, 'g', "Too small to recycle", "")
+VSC_F(surplus,			uint64_t, 0, 'g', "Too many for pool", "")
 
 #endif



More information about the varnish-commit mailing list