Commit d13c674d authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add stats counters for VSM usage/overflows.

Various minor polish to VSM area.
parent 40c0fef6
...@@ -850,7 +850,7 @@ int SES_Schedule(struct sess *sp); ...@@ -850,7 +850,7 @@ int SES_Schedule(struct sess *sp);
/* cache_shmlog.c */ /* cache_shmlog.c */
extern struct VSC_C_main *VSC_C_main; extern struct VSC_C_main *VSC_C_main;
void VSL_Init(void); void VSM_Init(void);
void *VSM_Alloc(unsigned size, const char *class, const char *type, void *VSM_Alloc(unsigned size, const char *class, const char *type,
const char *ident); const char *ident);
void VSM_Free(void *ptr); void VSM_Free(void *ptr);
......
...@@ -103,7 +103,7 @@ child_main(void) ...@@ -103,7 +103,7 @@ child_main(void)
THR_SetName("cache-main"); THR_SetName("cache-main");
VSL_Init(); /* First, LCK needs it. */ VSM_Init(); /* First, LCK needs it. */
LCK_Init(); /* Second, locking */ LCK_Init(); /* Second, locking */
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "cache_backend.h" // For w->vbc #include "cache_backend.h" // For w->vbc
#include "vmb.h" #include "vmb.h"
#include "vtim.h"
/* These cannot be struct lock, which depends on vsm/vsl working */ /* These cannot be struct lock, which depends on vsm/vsl working */
static pthread_mutex_t vsl_mtx; static pthread_mutex_t vsl_mtx;
...@@ -299,10 +300,26 @@ WSLB(struct worker *w, enum VSL_tag_e tag, const char *fmt, ...) ...@@ -299,10 +300,26 @@ WSLB(struct worker *w, enum VSL_tag_e tag, const char *fmt, ...)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void *
vsm_cleaner(void *priv)
{
(void)priv;
THR_SetName("vsm_cleaner");
while (1) {
AZ(pthread_mutex_lock(&vsm_mtx));
VSM_common_cleaner(heritage.vsm, VSC_C_main);
AZ(pthread_mutex_unlock(&vsm_mtx));
VTIM_sleep(1.1);
}
}
/*--------------------------------------------------------------------*/
void void
VSL_Init(void) VSM_Init(void)
{ {
uint32_t *vsl_log_start; uint32_t *vsl_log_start;
pthread_t tp;
AZ(pthread_mutex_init(&vsl_mtx, NULL)); AZ(pthread_mutex_init(&vsl_mtx, NULL));
AZ(pthread_mutex_init(&vsm_mtx, NULL)); AZ(pthread_mutex_init(&vsm_mtx, NULL));
...@@ -328,6 +345,8 @@ VSL_Init(void) ...@@ -328,6 +345,8 @@ VSL_Init(void)
// VSM_head->starttime = (intmax_t)VTIM_real(); // VSM_head->starttime = (intmax_t)VTIM_real();
memset(VSC_C_main, 0, sizeof *VSC_C_main); memset(VSC_C_main, 0, sizeof *VSC_C_main);
// VSM_head->child_pid = getpid(); // VSM_head->child_pid = getpid();
AZ(pthread_create(&tp, NULL, vsm_cleaner, NULL));
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
......
...@@ -69,12 +69,14 @@ void mgt_child_inherit(int fd, const char *what); ...@@ -69,12 +69,14 @@ void mgt_child_inherit(int fd, const char *what);
/* vsm.c */ /* vsm.c */
struct vsm_sc; struct vsm_sc;
struct VSC_C_main;
struct vsm_sc *VSM_common_new(void *ptr, ssize_t len); struct vsm_sc *VSM_common_new(void *ptr, ssize_t len);
void *VSM_common_alloc(struct vsm_sc *sc, ssize_t size, void *VSM_common_alloc(struct vsm_sc *sc, ssize_t size,
const char *class, const char *type, const char *ident); const char *class, const char *type, const char *ident);
void VSM_common_free(struct vsm_sc *sc, void *ptr); void VSM_common_free(struct vsm_sc *sc, void *ptr);
void VSM_common_delete(struct vsm_sc **sc); void VSM_common_delete(struct vsm_sc **sc);
void VSM_common_copy(struct vsm_sc *to, const struct vsm_sc *from); void VSM_common_copy(struct vsm_sc *to, const struct vsm_sc *from);
void VSM_common_cleaner(struct vsm_sc *sc, struct VSC_C_main *stats);
/*--------------------------------------------------------------------- /*---------------------------------------------------------------------
* Generic power-2 rounding macros * Generic power-2 rounding macros
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "common.h" #include "common.h"
#include "vapi/vsm_int.h" #include "vapi/vsm_int.h"
#include "vapi/vsc_int.h"
#include "vmb.h" #include "vmb.h"
#include "vtim.h" #include "vtim.h"
...@@ -69,6 +70,11 @@ struct vsm_sc { ...@@ -69,6 +70,11 @@ struct vsm_sc {
VTAILQ_HEAD(,vsm_range) r_cooling; VTAILQ_HEAD(,vsm_range) r_cooling;
VTAILQ_HEAD(,vsm_range) r_free; VTAILQ_HEAD(,vsm_range) r_free;
VTAILQ_HEAD(,vsm_range) r_bogus; VTAILQ_HEAD(,vsm_range) r_bogus;
uint64_t g_free;
uint64_t g_used;
uint64_t g_cooling;
uint64_t g_overflow;
uint64_t c_overflow;
}; };
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
...@@ -148,9 +154,36 @@ VSM_common_new(void *p, ssize_t l) ...@@ -148,9 +154,36 @@ VSM_common_new(void *p, ssize_t l)
vr->off = RUP2(sizeof(*sc->head), 16); vr->off = RUP2(sizeof(*sc->head), 16);
vr->len = RDN2(l - vr->off, 16); vr->len = RDN2(l - vr->off, 16);
VTAILQ_INSERT_TAIL(&sc->r_free, vr, list); VTAILQ_INSERT_TAIL(&sc->r_free, vr, list);
sc->g_free = vr->len;
return (sc); return (sc);
} }
/*--------------------------------------------------------------------
* Move from cooling list to free list
*/
void
VSM_common_cleaner(struct vsm_sc *sc, struct VSC_C_main *stats)
{
double now = VTIM_real();
struct vsm_range *vr, *vr2;
CHECK_OBJ_NOTNULL(sc, VSM_SC_MAGIC);
/* Move cooled off stuff to free list */
VTAILQ_FOREACH_SAFE(vr, &sc->r_cooling, list, vr2) {
if (vr->cool > now)
break;
VTAILQ_REMOVE(&sc->r_cooling, vr, list);
vsm_common_insert_free(sc, vr);
}
stats->vsm_free = sc->g_free;
stats->vsm_used = sc->g_used;
stats->vsm_cooling = sc->g_cooling;
stats->vsm_overflow = sc->g_overflow;
stats->vsm_overflowed = sc->c_overflow;
}
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Allocate a chunk from VSM * Allocate a chunk from VSM
*/ */
...@@ -160,7 +193,6 @@ VSM_common_alloc(struct vsm_sc *sc, ssize_t size, ...@@ -160,7 +193,6 @@ VSM_common_alloc(struct vsm_sc *sc, ssize_t size,
const char *class, const char *type, const char *ident) const char *class, const char *type, const char *ident)
{ {
struct vsm_range *vr, *vr2, *vr3; struct vsm_range *vr, *vr2, *vr3;
double now = VTIM_real();
unsigned l1, l2; unsigned l1, l2;
CHECK_OBJ_NOTNULL(sc, VSM_SC_MAGIC); CHECK_OBJ_NOTNULL(sc, VSM_SC_MAGIC);
...@@ -174,14 +206,6 @@ VSM_common_alloc(struct vsm_sc *sc, ssize_t size, ...@@ -174,14 +206,6 @@ VSM_common_alloc(struct vsm_sc *sc, ssize_t size,
AN(ident); AN(ident);
assert(strlen(ident) < sizeof(vr->chunk->ident)); assert(strlen(ident) < sizeof(vr->chunk->ident));
/* Move cooled off stuff to free list */
VTAILQ_FOREACH_SAFE(vr, &sc->r_cooling, list, vr2) {
if (vr->cool > now)
break;
VTAILQ_REMOVE(&sc->r_cooling, vr, list);
vsm_common_insert_free(sc, vr);
}
l1 = RUP2(size + sizeof(struct VSM_chunk), 16); l1 = RUP2(size + sizeof(struct VSM_chunk), 16);
l2 = RUP2(size + 2 * sizeof(struct VSM_chunk), 16); l2 = RUP2(size + 2 * sizeof(struct VSM_chunk), 16);
...@@ -213,12 +237,15 @@ VSM_common_alloc(struct vsm_sc *sc, ssize_t size, ...@@ -213,12 +237,15 @@ VSM_common_alloc(struct vsm_sc *sc, ssize_t size,
AN(vr); AN(vr);
vr->ptr = malloc(size); vr->ptr = malloc(size);
AN(vr->ptr); AN(vr->ptr);
vr->len = size;
VTAILQ_INSERT_TAIL(&sc->r_bogus, vr, list); VTAILQ_INSERT_TAIL(&sc->r_bogus, vr, list);
/* XXX: log + stats */ sc->g_overflow += vr->len;
sc->c_overflow += vr->len;
return (vr->ptr); return (vr->ptr);
} }
/* XXX: stats ? */ sc->g_free -= vr->len;
sc->g_used += vr->len;
/* Zero the entire allocation, to avoid garbage confusing readers */ /* Zero the entire allocation, to avoid garbage confusing readers */
memset(sc->b + vr->off, 0, vr->len); memset(sc->b + vr->off, 0, vr->len);
...@@ -263,7 +290,10 @@ VSM_common_free(struct vsm_sc *sc, void *ptr) ...@@ -263,7 +290,10 @@ VSM_common_free(struct vsm_sc *sc, void *ptr)
VTAILQ_FOREACH(vr, &sc->r_used, list) { VTAILQ_FOREACH(vr, &sc->r_used, list) {
if (vr->ptr != ptr) if (vr->ptr != ptr)
continue; continue;
/* XXX: stats ? */
sc->g_used -= vr->len;
sc->g_cooling += vr->len;
vr2 = VTAILQ_NEXT(vr, list); vr2 = VTAILQ_NEXT(vr, list);
VTAILQ_REMOVE(&sc->r_used, vr, list); VTAILQ_REMOVE(&sc->r_used, vr, list);
VTAILQ_INSERT_TAIL(&sc->r_cooling, vr, list); VTAILQ_INSERT_TAIL(&sc->r_cooling, vr, list);
...@@ -278,15 +308,18 @@ VSM_common_free(struct vsm_sc *sc, void *ptr) ...@@ -278,15 +308,18 @@ VSM_common_free(struct vsm_sc *sc, void *ptr)
VWMB(); VWMB();
return; return;
} }
/* Look in bogus list, free */ /* Look in bogus list, free */
VTAILQ_FOREACH(vr, &sc->r_bogus, list) { VTAILQ_FOREACH(vr, &sc->r_bogus, list) {
if (vr->ptr == ptr) { if (vr->ptr != ptr)
VTAILQ_REMOVE(&sc->r_bogus, vr, list); continue;
FREE_OBJ(vr);
/* XXX: stats ? */ sc->g_overflow -= vr->len;
free(ptr);
return; VTAILQ_REMOVE(&sc->r_bogus, vr, list);
} FREE_OBJ(vr);
free(ptr);
return;
} }
/* Panic */ /* Panic */
assert(ptr == NULL); assert(ptr == NULL);
...@@ -326,7 +359,7 @@ VSM_common_delete(struct vsm_sc **scp) ...@@ -326,7 +359,7 @@ VSM_common_delete(struct vsm_sc **scp)
} }
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Copy one VSM to another * Copy all chunks in one VSM segment to another VSM segment
*/ */
void void
......
...@@ -359,3 +359,38 @@ VSC_F(vmods, uint64_t, 0, 'i', "Loaded VMODs", "") ...@@ -359,3 +359,38 @@ VSC_F(vmods, uint64_t, 0, 'i', "Loaded VMODs", "")
VSC_F(n_gzip, uint64_t, 0, 'a', "Gzip operations", "") VSC_F(n_gzip, uint64_t, 0, 'a', "Gzip operations", "")
VSC_F(n_gunzip, uint64_t, 0, 'a', "Gunzip operations", "") VSC_F(n_gunzip, uint64_t, 0, 'a', "Gunzip operations", "")
/**********************************************************************/
VSC_F(vsm_free, uint64_t, 0, 'g',
"Free VSM space",
"Number of bytes free in the shared memory used to communicate"
" with tools like varnishstat, varnishlog etc."
)
VSC_F(vsm_used, uint64_t, 0, 'g',
"Used VSM space",
"Number of bytes used in the shared memory used to communicate"
" with tools like varnishstat, varnishlog etc."
)
VSC_F(vsm_cooling, uint64_t, 0, 'g',
"Cooling VSM space",
"Number of bytes which will soon (max 1 minute) be freed"
" in the shared memory used to communicate"
" with tools like varnishstat, varnishlog etc."
)
VSC_F(vsm_overflow, uint64_t, 0, 'g',
"Overflow VSM space",
"Number of bytes which does not fit"
" in the shared memory used to communicate"
" with tools like varnishstat, varnishlog etc."
)
VSC_F(vsm_overflowed, uint64_t, 0, 'c',
"Overflowed VSM space",
"Total number of bytes which did not fit"
" in the shared memory used to communicate"
" with tools like varnishstat, varnishlog etc."
)
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* In particular we want the readers to seamlessly jump from one VSM instance * In particular we want the readers to seamlessly jump from one VSM instance
* to another when the child restarts. * to another when the child restarts.
* *
* The VSM life-cycle there is: * The VSM segment life-cycle is:
* *
* Manager creates VSM file under temp name * Manager creates VSM file under temp name
* *
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
* it will zero the alloc_seq in it, before replacing the file. * it will zero the alloc_seq in it, before replacing the file.
* *
* Subscribers will have to monitor two things to make sure they have * Subscribers will have to monitor two things to make sure they have
* the current VSM instance: The alloc_seq field and the inode number * the current VSM instance: The alloc_seq field and the dev+inode
* of the path-name. The former check is by far the cheaper and the * of the path-name. The former check is by far the cheaper and the
* latter check should only be employed when lack of activity in the * latter check should only be employed when lack of activity in the
* VSM segment raises suspicion that something has happened. * VSM segment raises suspicion that something has happened.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment