[experimental-ims] 03e0bcf Write some generic code for a memory pool and apply it it VBC as the initial guineapig.

Geoff Simmons geoff at varnish-cache.org
Tue Jan 10 00:03:26 CET 2012


commit 03e0bcf1beebc82633cbba0a861060a650288058
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Dec 12 11:54:59 2011 +0000

    Write some generic code for a memory pool and apply it it VBC as
    the initial guineapig.
    
    We have a number of pools of objects we maintain dynamically and we
    will get more in the future, so having a generic facility makes sense.
    
    One particular aspect of some of our pools, is that the desired size
    of object is variable over time, for instance workspaces which
    depend on parameters etc.
    
    Using generic code will allow us to use systematic parameters and
    VSC stats for all pools, hopefully with some memory savings involved.

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index a4bae7f..0c3427e 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -34,6 +34,7 @@ varnishd_SOURCES = \
 	cache/cache_httpconn.c \
 	cache/cache_lck.c \
 	cache/cache_main.c \
+	cache/cache_mempool.c \
 	cache/cache_panic.c \
 	cache/cache_pipe.c \
 	cache/cache_pool.c \
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index ed6a3fd..edfe75f 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -99,10 +99,12 @@ struct cli;
 struct cli_proto;
 struct director;
 struct iovec;
+struct mempool;
 struct objcore;
 struct object;
 struct objhead;
 struct pool;
+struct poolparam;
 struct sess;
 struct sesspool;
 struct vbc;
@@ -667,6 +669,7 @@ void VDI_CloseFd(struct worker *wrk, struct vbc **vbp);
 void VDI_RecycleFd(struct worker *wrk, struct vbc **vbp);
 void VDI_AddHostHeader(struct worker *wrk, const struct vbc *vbc);
 void VBE_Poll(void);
+void VDI_Init(void);
 
 /* cache_backend_cfg.c */
 void VBE_InitCfg(void);
@@ -849,6 +852,15 @@ int Lck_CondWait(pthread_cond_t *cond, struct lock *lck, struct timespec *ts);
 #include "tbl/locks.h"
 #undef LOCK
 
+/* 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);
+
+
 /* cache_panic.c */
 void PAN_Init(void);
 
diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c
index 4d2f18a..333b9bf 100644
--- a/bin/varnishd/cache/cache_backend.c
+++ b/bin/varnishd/cache/cache_backend.c
@@ -43,6 +43,16 @@
 #include "vrt.h"
 #include "vtcp.h"
 
+static struct mempool	*vbcpool;
+
+static struct poolparam vbcpp = {
+	.min_pool	= 10,
+	.max_pool	= 100,
+	.max_age	= 60,
+};
+
+static unsigned		vbcps = sizeof(struct vbc);
+
 /*--------------------------------------------------------------------
  * The "simple" director really isn't, since thats where all the actual
  * connections happen.  Nontheless, pretend it is simple by sequestering
@@ -82,14 +92,7 @@ VBE_ReleaseConn(struct vbc *vc)
 	CHECK_OBJ_NOTNULL(vc, VBC_MAGIC);
 	assert(vc->backend == NULL);
 	assert(vc->fd < 0);
-
-	vc->addr = NULL;
-	vc->addrlen = 0;
-	vc->recycled = 0;
-	Lck_Lock(&VBE_mtx);
-	VSC_C_main->n_vbc--;
-	Lck_Unlock(&VBE_mtx);
-	FREE_OBJ(vc);
+	MPL_Free(vbcpool, vc);
 }
 
 #define FIND_TMO(tmx, dst, sp, be)		\
@@ -221,12 +224,10 @@ vbe_NewConn(void)
 {
 	struct vbc *vc;
 
-	ALLOC_OBJ(vc, VBC_MAGIC);
+	vc = MPL_Get(vbcpool, NULL);
 	XXXAN(vc);
+	vc->magic = VBC_MAGIC;
 	vc->fd = -1;
-	Lck_Lock(&VBE_mtx);
-	VSC_C_main->n_vbc++;
-	Lck_Unlock(&VBE_mtx);
 	return (vc);
 }
 
@@ -517,3 +518,11 @@ VRT_init_dir_simple(struct cli *cli, struct director **bp, int idx,
 
 	bp[idx] = &vs->dir;
 }
+
+void
+VDI_Init(void)
+{
+
+	vbcpool = MPL_New("vbc", NULL, &vbcpp, &vbcps);
+	AN(vbcpool);
+}
diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h
index 72a1283..a3ae5c2 100644
--- a/bin/varnishd/cache/cache_backend.h
+++ b/bin/varnishd/cache/cache_backend.h
@@ -170,7 +170,6 @@ void VBE_ReleaseConn(struct vbc *vc);
 struct backend *vdi_get_backend_if_simple(const struct director *d);
 
 /* cache_backend_cfg.c */
-extern struct lock VBE_mtx;
 void VBE_DropRefConn(struct backend *);
 void VBE_DropRefVcl(struct backend *);
 void VBE_DropRefLocked(struct backend *b);
diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c
index a47aa3c..c2d022d 100644
--- a/bin/varnishd/cache/cache_backend_cfg.c
+++ b/bin/varnishd/cache/cache_backend_cfg.c
@@ -43,9 +43,6 @@
 #include "vcli_priv.h"
 #include "vrt.h"
 
-struct lock VBE_mtx;
-
-
 /*
  * The list of backends is not locked, it is only ever accessed from
  * the CLI thread, so there is no need.
@@ -502,6 +499,5 @@ void
 VBE_InitCfg(void)
 {
 
-	Lck_New(&VBE_mtx, lck_vbe);
 	CLI_AddFuncs(backend_cmds);
 }
diff --git a/bin/varnishd/cache/cache_main.c b/bin/varnishd/cache/cache_main.c
index a10b0fe..2189104 100644
--- a/bin/varnishd/cache/cache_main.c
+++ b/bin/varnishd/cache/cache_main.c
@@ -117,6 +117,7 @@ child_main(void)
 
 	HTTP_Init();
 
+	VDI_Init();
 	VBO_Init();
 	VBE_InitCfg();
 	VBP_Init();
diff --git a/bin/varnishd/cache/cache_mempool.c b/bin/varnishd/cache/cache_mempool.c
new file mode 100644
index 0000000..6677c84
--- /dev/null
+++ b/bin/varnishd/cache/cache_mempool.c
@@ -0,0 +1,164 @@
+/*-
+ * Copyright (c) 2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Generic memory pool
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "config.h"
+
+#include "cache.h"
+
+struct memitem {
+	unsigned			magic;
+#define MEMITEM_MAGIC			0x42e55401
+	VTAILQ_ENTRY(memitem)		list;
+	unsigned			size;
+	double				payload;
+};
+
+struct mempool {
+	unsigned			magic;
+#define MEMPOOL_MAGIC			0x37a75a8d
+	VTAILQ_HEAD(,memitem)		list;
+	struct lock			*mtx;
+	struct lock			imtx;
+	const char			*name;
+	volatile struct poolparam	*param;
+	volatile unsigned		*cur_size;
+	struct VSC_C_mempool		*vsc;
+};
+
+struct mempool *
+MPL_New(const char *name,
+	struct lock *mtx,
+	volatile struct poolparam *pp,
+	volatile unsigned *cur_size)
+{
+	struct mempool *mpl;
+
+	ALLOC_OBJ(mpl, MEMPOOL_MAGIC);
+	AN(mpl);
+	mpl->name = name;
+	mpl->param = pp;
+	mpl->cur_size = cur_size;
+	mpl->mtx = mtx;
+	VTAILQ_INIT(&mpl->list);
+	Lck_New(&mpl->imtx, lck_mempool);
+	if (mpl->mtx == NULL)
+		mpl->mtx = &mpl->imtx;
+	/* XXX: prealloc min_pool */
+	mpl->vsc = VSM_Alloc(sizeof *mpl->vsc,
+	    VSC_CLASS, VSC_TYPE_MEMPOOL, name);
+	AN(mpl->vsc);
+	return (mpl);
+}
+
+void *
+MPL_GetLocked(struct mempool *mpl, unsigned *size)
+{
+	struct memitem *mi;
+	unsigned tsz;
+
+	CHECK_OBJ_NOTNULL(mpl, MEMPOOL_MAGIC);
+	Lck_AssertHeld(mpl->mtx);
+
+	mpl->vsc->allocs++;
+	mpl->vsc->live++;
+	do {
+		mi = VTAILQ_FIRST(&mpl->list);
+		if (mi == NULL)
+			break;
+		mpl->vsc->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);
+			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;
+	}
+	if (size != NULL)
+		*size = mi->size;
+	return (&mi->payload);
+}
+
+void
+MPL_FreeLocked(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);
+
+	if (mi->size < *mpl->cur_size) {
+		mpl->vsc->toosmall++;
+		FREE_OBJ(mi);
+	} else {
+		mpl->vsc->pool++;
+		memset(item, 0, mi->size);
+		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/common/params.h b/bin/varnishd/common/params.h
index 8fd777f..3f1821f 100644
--- a/bin/varnishd/common/params.h
+++ b/bin/varnishd/common/params.h
@@ -33,6 +33,12 @@
 
 #define VSM_CLASS_PARAM		"Params"
 
+struct poolparam {
+	unsigned		min_pool;
+	unsigned		max_pool;
+	double			max_age;
+};
+
 struct params {
 
 	/* Unprivileged user / group */
diff --git a/include/tbl/locks.h b/include/tbl/locks.h
index d86da01..697752d 100644
--- a/include/tbl/locks.h
+++ b/include/tbl/locks.h
@@ -46,9 +46,9 @@ LOCK(lru)
 LOCK(cli)
 LOCK(ban)
 LOCK(vbp)
-LOCK(vbe)
 LOCK(backend)
 LOCK(vcapace)
 LOCK(nbusyobj)
 LOCK(busyobj)
+LOCK(mempool)
 /*lint -restore */
diff --git a/include/tbl/vsc_all.h b/include/tbl/vsc_all.h
index 4d7b927..ae42507 100644
--- a/include/tbl/vsc_all.h
+++ b/include/tbl/vsc_all.h
@@ -56,3 +56,9 @@ VSC_DO(VBE, vbe, VSC_TYPE_VBE)
 #include "tbl/vsc_fields.h"
 #undef VSC_DO_VBE
 VSC_DONE(VBE, vbe, VSC_TYPE_VBE)
+
+VSC_DO(MEMPOOL, mempool, VSC_TYPE_MEMPOOL)
+#define VSC_DO_MEMPOOL
+#include "tbl/vsc_fields.h"
+#undef VSC_DO_MEMPOOL
+VSC_DONE(MEMPOOL, mempool, VSC_TYPE_MEMPOOL)
diff --git a/include/tbl/vsc_f_main.h b/include/tbl/vsc_f_main.h
index ab8415c..c8c4ecb 100644
--- a/include/tbl/vsc_f_main.h
+++ b/include/tbl/vsc_f_main.h
@@ -259,8 +259,6 @@ VSC_F(n_objectcore,		uint64_t, 1, 'i', "N struct objectcore", "")
 VSC_F(n_objecthead,		uint64_t, 1, 'i', "N struct objecthead", "")
 VSC_F(n_waitinglist,		uint64_t, 1, 'i', "N struct waitinglist", "")
 
-VSC_F(n_vbc,		uint64_t, 0, 'i', "N struct vbc", "")
-
 VSC_F(n_backend,		uint64_t, 0, 'i', "N backends", "")
 
 VSC_F(n_expired,		uint64_t, 0, 'i', "N expired objects", "")
diff --git a/include/tbl/vsc_fields.h b/include/tbl/vsc_fields.h
index 60cde5d..cc72903 100644
--- a/include/tbl/vsc_fields.h
+++ b/include/tbl/vsc_fields.h
@@ -106,3 +106,15 @@ VSC_F(happy,		uint64_t, 0, 'b', "Happy health probes", "")
 
 #endif
 
+/**********************************************************************/
+#ifdef VSC_DO_MEMPOOL
+
+VSC_F(allocs,			uint64_t, 0, 'c', "Allocations", "")
+VSC_F(frees,			uint64_t, 0, 'c', "Frees", "")
+VSC_F(live,			uint64_t, 0, 'g', "In use", "")
+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", "")
+
+#endif
diff --git a/include/vapi/vsc_int.h b/include/vapi/vsc_int.h
index 6ceb723..95346e3 100644
--- a/include/vapi/vsc_int.h
+++ b/include/vapi/vsc_int.h
@@ -28,13 +28,14 @@
  *
  */
 
-#define VSC_CLASS          "Stat"
+#define VSC_CLASS		"Stat"
 
 #define VSC_TYPE_MAIN		""
-#define VSC_TYPE_SMA	"SMA"
-#define VSC_TYPE_SMF	"SMF"
-#define VSC_TYPE_VBE	"VBE"
-#define VSC_TYPE_LCK	"LCK"
+#define VSC_TYPE_SMA		"SMA"
+#define VSC_TYPE_SMF		"SMF"
+#define VSC_TYPE_VBE		"VBE"
+#define VSC_TYPE_LCK		"LCK"
+#define VSC_TYPE_MEMPOOL	"MEMPOOL"
 
 #define VSC_F(n, t, l, f, e, d)	t n;
 



More information about the varnish-commit mailing list