[experimental-ims] e9b524b Add the mempool guard-thread
Geoff Simmons
geoff at varnish-cache.org
Tue Jan 10 00:03:27 CET 2012
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