[master] 676064d Add timeouts and comprehensive test-case for memorypool gymnastics.
Poul-Henning Kamp
phk at varnish-cache.org
Wed Dec 21 20:04:34 CET 2011
commit 676064df3932eb64b2aaa8e526c2cd7d5a45d226
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Wed Dec 21 11:16:23 2011 +0000
Add timeouts and comprehensive test-case for memorypool gymnastics.
diff --git a/bin/varnishd/cache/cache_mempool.c b/bin/varnishd/cache/cache_mempool.c
index ac4abf2..92e38d2 100644
--- a/bin/varnishd/cache/cache_mempool.c
+++ b/bin/varnishd/cache/cache_mempool.c
@@ -42,14 +42,17 @@ struct memitem {
#define MEMITEM_MAGIC 0x42e55401
VTAILQ_ENTRY(memitem) list;
unsigned size;
- double payload;
+ double touched;
+ char payload;
};
+VTAILQ_HEAD(memhead_s, memitem);
+
struct mempool {
unsigned magic;
#define MEMPOOL_MAGIC 0x37a75a8d
- VTAILQ_HEAD(,memitem) list;
- VTAILQ_HEAD(,memitem) surplus;
+ struct memhead_s list;
+ struct memhead_s surplus;
struct lock *mtx;
struct lock imtx;
const char *name;
@@ -58,6 +61,7 @@ struct mempool {
struct VSC_C_mempool *vsc;
unsigned n_pool;
pthread_t thread;
+ double t_now;
};
/*---------------------------------------------------------------------
@@ -81,21 +85,26 @@ mpl_alloc(const struct mempool *mpl)
/*---------------------------------------------------------------------
* Pool-guard
* Attempt to keep number of free items in pool inside bounds with
- * minimum locking activity.
+ * minimum locking activity, and keep an eye on items at the tail
+ * of the list not getting too old.
*/
+#include <stdio.h>
+
static void *
mpl_guard(void *priv)
{
struct mempool *mpl;
struct memitem *mi = NULL;
double mpl_slp __state_variable__(mpl_slp);
+ double last = 0;
CAST_OBJ_NOTNULL(mpl, priv, MEMPOOL_MAGIC);
mpl_slp = 0.15; // random
while (1) {
VTIM_sleep(mpl_slp);
mpl_slp = 0.814; // random
+ mpl->t_now = VTIM_real();
if (mi != NULL && (mpl->n_pool > mpl->param->max_pool ||
mi->size < *mpl->cur_size)) {
@@ -106,45 +115,69 @@ mpl_guard(void *priv)
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 if (last + .1 * mpl->param->max_age < mpl->t_now) {
+ /* should do */
} else {
- continue; /* cannot do */
+ continue; /* nothing to do */
}
- mpl_slp = 0.314;
+ mpl_slp = 0.314; // random
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++;
+ mi->touched = mpl->t_now;
VTAILQ_INSERT_HEAD(&mpl->list, mi, list);
mi = NULL;
+ mpl_slp = .01; // random
+
}
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->vsc->surplus++;
mpl->n_pool--;
VTAILQ_REMOVE(&mpl->list, mi, list);
+ mpl_slp = .01; // random
}
if (mi == NULL) {
mi = VTAILQ_FIRST(&mpl->surplus);
if (mi != NULL) {
CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC);
VTAILQ_REMOVE(&mpl->surplus, mi, list);
+ mpl_slp = .01; // random
}
}
+ if (mi == NULL && mpl->n_pool > mpl->param->min_pool) {
+ mi = VTAILQ_LAST(&mpl->list, memhead_s);
+ CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC);
+ if (mi->touched + mpl->param->max_age < mpl->t_now) {
+ mpl->vsc->pool--;
+ mpl->vsc->timeout++;
+ mpl->n_pool--;
+ VTAILQ_REMOVE(&mpl->list, mi, list);
+ mpl_slp = .01; // random
+ } else {
+ mi = NULL;
+ last = mpl->t_now;
+ }
+ } else if (mpl->n_pool <= mpl->param->min_pool) {
+ last = mpl->t_now;
+ }
+
Lck_Unlock(mpl->mtx);
if (mi != NULL) {
@@ -250,6 +283,7 @@ MPL_Free(struct mempool *mpl, void *item)
} else {
mpl->vsc->pool++;
mpl->n_pool++;
+ mi->touched = mpl->t_now;
VTAILQ_INSERT_HEAD(&mpl->list, mi, list);
}
diff --git a/bin/varnishtest/tests/c00050.vtc b/bin/varnishtest/tests/c00050.vtc
new file mode 100644
index 0000000..340563b
--- /dev/null
+++ b/bin/varnishtest/tests/c00050.vtc
@@ -0,0 +1,29 @@
+varnishtest "Memory pool gymnastics"
+
+server s1 { } -start
+
+varnish v1 -vcl+backend {} -start
+
+delay 1
+
+varnish v1 -expect MEMPOOL.vbc.pool == 10
+
+varnish v1 -cliok "param.set vbc_pool 90,100,100"
+
+delay 1
+
+varnish v1 -expect MEMPOOL.vbc.pool == 90
+
+varnish v1 -cliok "param.set vbc_pool 50,80,100"
+
+delay 1
+
+varnish v1 -expect MEMPOOL.vbc.pool == 80
+varnish v1 -expect MEMPOOL.vbc.surplus == 10
+
+varnish v1 -cliok "param.set vbc_pool 10,80,1"
+
+delay 1
+
+varnish v1 -expect MEMPOOL.vbc.pool == 10
+varnish v1 -expect MEMPOOL.vbc.timeout == 70
More information about the varnish-commit
mailing list