Commit 98b2ef2f authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add a delta-stats structure to worker threads and keep

track of n_object and n_objecthead in them.

Accumulate into global stats after work is done if the lock is
free and always before going idle.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@3796 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 4187eeb7
...@@ -178,12 +178,25 @@ struct acct { ...@@ -178,12 +178,25 @@ struct acct {
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
#define L0(n)
#define L1(n) int n;
#define MAC_STAT(n, t, l, f, e) L##l(n)
struct dstat {
#include "stat_field.h"
};
#undef MAC_STAT
#undef L0
#undef L1
/*--------------------------------------------------------------------*/
struct worker { struct worker {
unsigned magic; unsigned magic;
#define WORKER_MAGIC 0x6391adcf #define WORKER_MAGIC 0x6391adcf
struct objhead *nobjhead; struct objhead *nobjhead;
struct object *nobj; struct object *nobj;
struct objcore *nobjcore; struct objcore *nobjcore;
struct dstat *stats;
double lastused; double lastused;
...@@ -551,6 +564,7 @@ void PipeSession(struct sess *sp); ...@@ -551,6 +564,7 @@ void PipeSession(struct sess *sp);
void WRK_Init(void); void WRK_Init(void);
int WRK_Queue(struct workreq *wrq); int WRK_Queue(struct workreq *wrq);
void WRK_QueueSession(struct sess *sp); void WRK_QueueSession(struct sess *sp);
void WRK_SumStat(struct worker *w);
void WRW_Reserve(struct worker *w, int *fd); void WRW_Reserve(struct worker *w, int *fd);
void WRW_Release(struct worker *w); void WRW_Release(struct worker *w);
......
...@@ -181,7 +181,7 @@ cnt_deliver(struct sess *sp) ...@@ -181,7 +181,7 @@ cnt_deliver(struct sess *sp)
RES_WriteObj(sp); RES_WriteObj(sp);
AZ(sp->wrk->wfd); AZ(sp->wrk->wfd);
HSH_Deref(&sp->obj); HSH_Deref(sp->wrk, &sp->obj);
sp->step = STP_DONE; sp->step = STP_DONE;
return (0); return (0);
} }
...@@ -527,7 +527,7 @@ cnt_hit(struct sess *sp) ...@@ -527,7 +527,7 @@ cnt_hit(struct sess *sp)
} }
/* Drop our object, we won't need it */ /* Drop our object, we won't need it */
HSH_Deref(&sp->obj); HSH_Deref(sp->wrk, &sp->obj);
switch(sp->handling) { switch(sp->handling) {
case VCL_RET_PASS: case VCL_RET_PASS:
...@@ -611,7 +611,7 @@ cnt_lookup(struct sess *sp) ...@@ -611,7 +611,7 @@ cnt_lookup(struct sess *sp)
if (sp->obj->objcore->flags & OC_F_PASS) { if (sp->obj->objcore->flags & OC_F_PASS) {
VSL_stats->cache_hitpass++; VSL_stats->cache_hitpass++;
WSP(sp, SLT_HitPass, "%u", sp->obj->xid); WSP(sp, SLT_HitPass, "%u", sp->obj->xid);
HSH_Deref(&sp->obj); HSH_Deref(sp->wrk, &sp->obj);
sp->step = STP_PASS; sp->step = STP_PASS;
return (0); return (0);
} }
......
...@@ -217,16 +217,20 @@ exp_timer(void *arg) ...@@ -217,16 +217,20 @@ exp_timer(void *arg)
double t; double t;
struct sess *sp; struct sess *sp;
unsigned char logbuf[1024]; /* XXX size ? */ unsigned char logbuf[1024]; /* XXX size ? */
struct dstat stats;
THR_SetName("cache-timeout"); THR_SetName("cache-timeout");
(void)arg; (void)arg;
sp = SES_New(NULL, 0); sp = SES_New(NULL, 0);
XXXAN(sp); XXXAN(sp);
memset(&ww, 0, sizeof ww);
memset(&stats, 0, sizeof stats);
sp->wrk = &ww; sp->wrk = &ww;
ww.magic = WORKER_MAGIC; ww.magic = WORKER_MAGIC;
ww.wlp = ww.wlb = logbuf; ww.wlp = ww.wlb = logbuf;
ww.wle = logbuf + sizeof logbuf; ww.wle = logbuf + sizeof logbuf;
ww.stats = &stats;
AZ(sleep(10)); /* XXX: Takes time for VCL to arrive */ AZ(sleep(10)); /* XXX: Takes time for VCL to arrive */
VCL_Get(&sp->vcl); VCL_Get(&sp->vcl);
...@@ -238,6 +242,7 @@ exp_timer(void *arg) ...@@ -238,6 +242,7 @@ exp_timer(void *arg)
if (oc == NULL || oc->timer_when > t) { /* XXX: > or >= ? */ if (oc == NULL || oc->timer_when > t) { /* XXX: > or >= ? */
Lck_Unlock(&exp_mtx); Lck_Unlock(&exp_mtx);
WSL_Flush(&ww, 0); WSL_Flush(&ww, 0);
WRK_SumStat(&ww);
AZ(sleep(1)); AZ(sleep(1));
VCL_Refresh(&sp->vcl); VCL_Refresh(&sp->vcl);
t = TIM_real(); t = TIM_real();
...@@ -277,7 +282,7 @@ exp_timer(void *arg) ...@@ -277,7 +282,7 @@ exp_timer(void *arg)
oc->flags &= ~OC_F_ONLRU; oc->flags &= ~OC_F_ONLRU;
VSL_stats->n_expired++; VSL_stats->n_expired++;
Lck_Unlock(&exp_mtx); Lck_Unlock(&exp_mtx);
HSH_Deref(&o); HSH_Deref(&ww, &o);
} }
} }
...@@ -344,7 +349,7 @@ EXP_NukeOne(struct sess *sp) ...@@ -344,7 +349,7 @@ EXP_NukeOne(struct sess *sp)
if (sp->handling == VCL_RET_DISCARD) { if (sp->handling == VCL_RET_DISCARD) {
WSL(sp->wrk, SLT_ExpKill, 0, "%u LRU", o->xid); WSL(sp->wrk, SLT_ExpKill, 0, "%u LRU", o->xid);
HSH_Deref(&o); HSH_Deref(sp->wrk, &o);
return (1); return (1);
} }
......
...@@ -109,7 +109,7 @@ HSH_Prealloc(struct sess *sp) ...@@ -109,7 +109,7 @@ HSH_Prealloc(struct sess *sp)
VTAILQ_INIT(&oh->waitinglist); VTAILQ_INIT(&oh->waitinglist);
Lck_New(&oh->mtx); Lck_New(&oh->mtx);
w->nobjhead = oh; w->nobjhead = oh;
VSL_stats->n_objecthead++; w->stats->n_objecthead++;
} }
CHECK_OBJ_NOTNULL(w->nobjhead, OBJHEAD_MAGIC); CHECK_OBJ_NOTNULL(w->nobjhead, OBJHEAD_MAGIC);
...@@ -134,20 +134,20 @@ HSH_Prealloc(struct sess *sp) ...@@ -134,20 +134,20 @@ HSH_Prealloc(struct sess *sp)
VTAILQ_INIT(&o->store); VTAILQ_INIT(&o->store);
VTAILQ_INIT(&o->esibits); VTAILQ_INIT(&o->esibits);
w->nobj = o; w->nobj = o;
VSL_stats->n_object++; w->stats->n_object++;
} }
CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC);
} }
void void
HSH_DeleteObjHead(struct objhead *oh) HSH_DeleteObjHead(struct worker *w, struct objhead *oh)
{ {
AZ(oh->refcnt); AZ(oh->refcnt);
assert(VTAILQ_EMPTY(&oh->objcs)); assert(VTAILQ_EMPTY(&oh->objcs));
Lck_Delete(&oh->mtx); Lck_Delete(&oh->mtx);
VSL_stats->n_objecthead--; w->stats->n_objecthead--;
free(oh->hash); free(oh->hash);
FREE_OBJ(oh); FREE_OBJ(oh);
} }
...@@ -398,7 +398,7 @@ HSH_Drop(struct sess *sp) ...@@ -398,7 +398,7 @@ HSH_Drop(struct sess *sp)
o->cacheable = 0; o->cacheable = 0;
if (o->objcore != NULL) /* Pass has no objcore */ if (o->objcore != NULL) /* Pass has no objcore */
HSH_Unbusy(sp); HSH_Unbusy(sp);
HSH_Deref(&sp->obj); HSH_Deref(sp->wrk, &sp->obj);
} }
void void
...@@ -434,7 +434,7 @@ HSH_Unbusy(const struct sess *sp) ...@@ -434,7 +434,7 @@ HSH_Unbusy(const struct sess *sp)
if (oh != NULL) if (oh != NULL)
Lck_Unlock(&oh->mtx); Lck_Unlock(&oh->mtx);
if (parent != NULL) if (parent != NULL)
HSH_Deref(&parent); HSH_Deref(sp->wrk, &parent);
} }
void void
...@@ -452,7 +452,7 @@ HSH_Ref(struct object *o) ...@@ -452,7 +452,7 @@ HSH_Ref(struct object *o)
} }
void void
HSH_Deref(struct object **oo) HSH_Deref(struct worker *w, struct object **oo)
{ {
struct object *o; struct object *o;
struct objhead *oh; struct objhead *oh;
...@@ -498,7 +498,7 @@ HSH_Deref(struct object **oo) ...@@ -498,7 +498,7 @@ HSH_Deref(struct object **oo)
ESI_Destroy(o); ESI_Destroy(o);
HSH_Freestore(o); HSH_Freestore(o);
STV_free(o->objstore); STV_free(o->objstore);
VSL_stats->n_object--; w->stats->n_object--;
if (oh == NULL) { if (oh == NULL) {
AZ(oc); AZ(oc);
...@@ -510,7 +510,7 @@ HSH_Deref(struct object **oo) ...@@ -510,7 +510,7 @@ HSH_Deref(struct object **oo)
assert(oh->refcnt > 0); assert(oh->refcnt > 0);
if (hash->deref(oh)) if (hash->deref(oh))
return; return;
HSH_DeleteObjHead(oh); HSH_DeleteObjHead(w, oh);
} }
void void
......
...@@ -98,6 +98,7 @@ static unsigned nthr_max; ...@@ -98,6 +98,7 @@ static unsigned nthr_max;
static pthread_cond_t herder_cond; static pthread_cond_t herder_cond;
static struct lock herder_mtx; static struct lock herder_mtx;
static struct lock wstat_mtx;
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Write data to fd * Write data to fd
...@@ -264,6 +265,31 @@ WRW_Sendfile(struct worker *w, int fd, off_t off, unsigned len) ...@@ -264,6 +265,31 @@ WRW_Sendfile(struct worker *w, int fd, off_t off, unsigned len)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void
wrk_sumstat(struct worker *w)
{
Lck_AssertHeld(&wstat_mtx);
#define L0(n)
#define L1(n) VSL_stats->n += w->stats->n
#define MAC_STAT(n, t, l, f, d) L##l(n);
#include "stat_field.h"
#undef MAC_STAT
#undef L0
#undef L1
memset(w->stats, 0, sizeof *w->stats);
}
void
WRK_SumStat(struct worker *w)
{
Lck_Lock(&wstat_mtx);
wrk_sumstat(w);
Lck_Unlock(&wstat_mtx);
}
/*--------------------------------------------------------------------*/
static void * static void *
wrk_thread(void *priv) wrk_thread(void *priv)
{ {
...@@ -271,12 +297,16 @@ wrk_thread(void *priv) ...@@ -271,12 +297,16 @@ wrk_thread(void *priv)
struct wq *qp; struct wq *qp;
unsigned char wlog[params->shm_workspace]; unsigned char wlog[params->shm_workspace];
struct SHA256Context sha256; struct SHA256Context sha256;
struct dstat stats;
unsigned stats_clean = 0;
THR_SetName("cache-worker"); THR_SetName("cache-worker");
w = &ww; w = &ww;
CAST_OBJ_NOTNULL(qp, priv, WQ_MAGIC); CAST_OBJ_NOTNULL(qp, priv, WQ_MAGIC);
memset(w, 0, sizeof *w); memset(w, 0, sizeof *w);
memset(&stats, 0, sizeof stats);
w->magic = WORKER_MAGIC; w->magic = WORKER_MAGIC;
w->stats = &stats;
w->lastused = NAN; w->lastused = NAN;
w->wlb = w->wlp = wlog; w->wlb = w->wlp = wlog;
w->wle = wlog + sizeof wlog; w->wle = wlog + sizeof wlog;
...@@ -299,6 +329,12 @@ wrk_thread(void *priv) ...@@ -299,6 +329,12 @@ wrk_thread(void *priv)
if (isnan(w->lastused)) if (isnan(w->lastused))
w->lastused = TIM_real(); w->lastused = TIM_real();
VTAILQ_INSERT_HEAD(&qp->idle, w, list); VTAILQ_INSERT_HEAD(&qp->idle, w, list);
if (!stats_clean) {
Lck_Lock(&wstat_mtx);
wrk_sumstat(w);
stats_clean = 1;
Lck_Unlock(&wstat_mtx);
}
Lck_CondWait(&w->cond, &qp->mtx); Lck_CondWait(&w->cond, &qp->mtx);
} }
if (w->wrq == NULL) if (w->wrq == NULL)
...@@ -307,14 +343,21 @@ wrk_thread(void *priv) ...@@ -307,14 +343,21 @@ wrk_thread(void *priv)
AN(w->wrq); AN(w->wrq);
AN(w->wrq->func); AN(w->wrq->func);
w->lastused = NAN; w->lastused = NAN;
stats_clean = 0;
w->wrq->func(w, w->wrq->priv); w->wrq->func(w, w->wrq->priv);
AZ(w->wfd); AZ(w->wfd);
assert(w->wlp == w->wlb); assert(w->wlp == w->wlb);
w->wrq = NULL; w->wrq = NULL;
if (!Lck_Trylock(&wstat_mtx)) {
wrk_sumstat(w);
stats_clean = 1;
Lck_Unlock(&wstat_mtx);
}
Lck_Lock(&qp->mtx); Lck_Lock(&qp->mtx);
} }
qp->nthr--; qp->nthr--;
Lck_Unlock(&qp->mtx); Lck_Unlock(&qp->mtx);
AN(stats_clean);
VSL(SLT_WorkThread, 0, "%p end", w); VSL(SLT_WorkThread, 0, "%p end", w);
if (w->vcl != NULL) if (w->vcl != NULL)
...@@ -627,6 +670,7 @@ WRK_Init(void) ...@@ -627,6 +670,7 @@ WRK_Init(void)
AZ(pthread_cond_init(&herder_cond, NULL)); AZ(pthread_cond_init(&herder_cond, NULL));
Lck_New(&herder_mtx); Lck_New(&herder_mtx);
Lck_New(&wstat_mtx);
wrk_addpools(params->wthread_pools); wrk_addpools(params->wthread_pools);
AZ(pthread_create(&tp, NULL, wrk_herdtimer_thread, NULL)); AZ(pthread_create(&tp, NULL, wrk_herdtimer_thread, NULL));
......
...@@ -345,6 +345,13 @@ hcb_cleaner(void *priv) ...@@ -345,6 +345,13 @@ hcb_cleaner(void *priv)
{ {
struct objhead *oh, *oh2; struct objhead *oh, *oh2;
struct hcb_y *y; struct hcb_y *y;
struct worker ww;
struct dstat stats;
memset(&ww, 0, sizeof ww);
memset(&stats, 0, sizeof stats);
ww.magic = WORKER_MAGIC;
ww.stats = &stats;
THR_SetName("hcb_cleaner"); THR_SetName("hcb_cleaner");
(void)priv; (void)priv;
...@@ -361,10 +368,11 @@ hcb_cleaner(void *priv) ...@@ -361,10 +368,11 @@ hcb_cleaner(void *priv)
fprintf(stderr, "OH %p is cold enough\n", oh); fprintf(stderr, "OH %p is cold enough\n", oh);
#endif #endif
oh->refcnt = 0; oh->refcnt = 0;
HSH_DeleteObjHead(oh); HSH_DeleteObjHead(&ww, oh);
} }
} }
Lck_Unlock(&hcb_mtx); Lck_Unlock(&hcb_mtx);
WRK_SumStat(&ww);
} }
} }
......
...@@ -50,13 +50,11 @@ struct hash_slinger { ...@@ -50,13 +50,11 @@ struct hash_slinger {
/* cache_hash.c */ /* cache_hash.c */
void HSH_Prealloc(struct sess *sp); void HSH_Prealloc(struct sess *sp);
void HSH_DeleteObjHead(struct objhead *oh);
void HSH_Freestore(struct object *o); void HSH_Freestore(struct object *o);
void HSH_Copy(const struct sess *sp, struct objhead *o); void HSH_Copy(const struct sess *sp, struct objhead *o);
struct object *HSH_Lookup(struct sess *sp); struct object *HSH_Lookup(struct sess *sp);
void HSH_Unbusy(const struct sess *sp); void HSH_Unbusy(const struct sess *sp);
void HSH_Ref(struct object *o); void HSH_Ref(struct object *o);
void HSH_Deref(struct object **o);
void HSH_Drop(struct sess *sp); void HSH_Drop(struct sess *sp);
double HSH_Grace(double g); double HSH_Grace(double g);
void HSH_Init(void); void HSH_Init(void);
...@@ -100,4 +98,6 @@ struct objhead { ...@@ -100,4 +98,6 @@ struct objhead {
}; };
extern unsigned save_hash; extern unsigned save_hash;
void HSH_DeleteObjHead(struct worker *w, struct objhead *oh);
void HSH_Deref(struct worker *w, struct object **o);
#endif /* VARNISH_CACHE_CHILD */ #endif /* VARNISH_CACHE_CHILD */
...@@ -49,8 +49,8 @@ MAC_STAT(n_srcaddr, uint64_t, 0, 'i', "N struct srcaddr") ...@@ -49,8 +49,8 @@ MAC_STAT(n_srcaddr, uint64_t, 0, 'i', "N struct srcaddr")
MAC_STAT(n_srcaddr_act, uint64_t, 0, 'i', "N active struct srcaddr") MAC_STAT(n_srcaddr_act, uint64_t, 0, 'i', "N active struct srcaddr")
MAC_STAT(n_sess_mem, uint64_t, 0, 'i', "N struct sess_mem") MAC_STAT(n_sess_mem, uint64_t, 0, 'i', "N struct sess_mem")
MAC_STAT(n_sess, uint64_t, 0, 'i', "N struct sess") MAC_STAT(n_sess, uint64_t, 0, 'i', "N struct sess")
MAC_STAT(n_object, uint64_t, 0, 'i', "N struct object") MAC_STAT(n_object, uint64_t, 1, 'i', "N struct object")
MAC_STAT(n_objecthead, uint64_t, 0, 'i', "N struct objecthead") MAC_STAT(n_objecthead, uint64_t, 1, 'i', "N struct objecthead")
MAC_STAT(n_smf, uint64_t, 0, 'i', "N struct smf") MAC_STAT(n_smf, uint64_t, 0, 'i', "N struct smf")
MAC_STAT(n_smf_frag, uint64_t, 0, 'i', "N small free smf") MAC_STAT(n_smf_frag, uint64_t, 0, 'i', "N small free smf")
MAC_STAT(n_smf_large, uint64_t, 0, 'i', "N large free smf") MAC_STAT(n_smf_large, uint64_t, 0, 'i', "N large free smf")
......
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