From: phk Date: Fri, 20 Feb 2009 15:25:06 +0000 (+0000) Subject: Add a delta-stats structure to worker threads and keep X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=466441c912a1a0c0d5d08ae7c09c7a3dfd2b3cdf;p=varnish 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: svn+ssh://projects.linpro.no/svn/varnish/trunk@3796 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index 5345988b..af1a2945 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -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 { unsigned magic; #define WORKER_MAGIC 0x6391adcf struct objhead *nobjhead; struct object *nobj; struct objcore *nobjcore; + struct dstat *stats; double lastused; @@ -551,6 +564,7 @@ void PipeSession(struct sess *sp); void WRK_Init(void); int WRK_Queue(struct workreq *wrq); void WRK_QueueSession(struct sess *sp); +void WRK_SumStat(struct worker *w); void WRW_Reserve(struct worker *w, int *fd); void WRW_Release(struct worker *w); diff --git a/varnish-cache/bin/varnishd/cache_center.c b/varnish-cache/bin/varnishd/cache_center.c index 8f5e7cd2..a64762ed 100644 --- a/varnish-cache/bin/varnishd/cache_center.c +++ b/varnish-cache/bin/varnishd/cache_center.c @@ -181,7 +181,7 @@ cnt_deliver(struct sess *sp) RES_WriteObj(sp); AZ(sp->wrk->wfd); - HSH_Deref(&sp->obj); + HSH_Deref(sp->wrk, &sp->obj); sp->step = STP_DONE; return (0); } @@ -527,7 +527,7 @@ cnt_hit(struct sess *sp) } /* Drop our object, we won't need it */ - HSH_Deref(&sp->obj); + HSH_Deref(sp->wrk, &sp->obj); switch(sp->handling) { case VCL_RET_PASS: @@ -611,7 +611,7 @@ cnt_lookup(struct sess *sp) if (sp->obj->objcore->flags & OC_F_PASS) { VSL_stats->cache_hitpass++; WSP(sp, SLT_HitPass, "%u", sp->obj->xid); - HSH_Deref(&sp->obj); + HSH_Deref(sp->wrk, &sp->obj); sp->step = STP_PASS; return (0); } diff --git a/varnish-cache/bin/varnishd/cache_expire.c b/varnish-cache/bin/varnishd/cache_expire.c index b96c831c..41f4804d 100644 --- a/varnish-cache/bin/varnishd/cache_expire.c +++ b/varnish-cache/bin/varnishd/cache_expire.c @@ -217,16 +217,20 @@ exp_timer(void *arg) double t; struct sess *sp; unsigned char logbuf[1024]; /* XXX size ? */ + struct dstat stats; THR_SetName("cache-timeout"); (void)arg; sp = SES_New(NULL, 0); XXXAN(sp); + memset(&ww, 0, sizeof ww); + memset(&stats, 0, sizeof stats); sp->wrk = &ww; ww.magic = WORKER_MAGIC; ww.wlp = ww.wlb = logbuf; ww.wle = logbuf + sizeof logbuf; + ww.stats = &stats; AZ(sleep(10)); /* XXX: Takes time for VCL to arrive */ VCL_Get(&sp->vcl); @@ -238,6 +242,7 @@ exp_timer(void *arg) if (oc == NULL || oc->timer_when > t) { /* XXX: > or >= ? */ Lck_Unlock(&exp_mtx); WSL_Flush(&ww, 0); + WRK_SumStat(&ww); AZ(sleep(1)); VCL_Refresh(&sp->vcl); t = TIM_real(); @@ -277,7 +282,7 @@ exp_timer(void *arg) oc->flags &= ~OC_F_ONLRU; VSL_stats->n_expired++; Lck_Unlock(&exp_mtx); - HSH_Deref(&o); + HSH_Deref(&ww, &o); } } @@ -344,7 +349,7 @@ EXP_NukeOne(struct sess *sp) if (sp->handling == VCL_RET_DISCARD) { WSL(sp->wrk, SLT_ExpKill, 0, "%u LRU", o->xid); - HSH_Deref(&o); + HSH_Deref(sp->wrk, &o); return (1); } diff --git a/varnish-cache/bin/varnishd/cache_hash.c b/varnish-cache/bin/varnishd/cache_hash.c index 3b704fe4..f416e28d 100644 --- a/varnish-cache/bin/varnishd/cache_hash.c +++ b/varnish-cache/bin/varnishd/cache_hash.c @@ -109,7 +109,7 @@ HSH_Prealloc(struct sess *sp) VTAILQ_INIT(&oh->waitinglist); Lck_New(&oh->mtx); w->nobjhead = oh; - VSL_stats->n_objecthead++; + w->stats->n_objecthead++; } CHECK_OBJ_NOTNULL(w->nobjhead, OBJHEAD_MAGIC); @@ -134,20 +134,20 @@ HSH_Prealloc(struct sess *sp) VTAILQ_INIT(&o->store); VTAILQ_INIT(&o->esibits); w->nobj = o; - VSL_stats->n_object++; + w->stats->n_object++; } CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC); } void -HSH_DeleteObjHead(struct objhead *oh) +HSH_DeleteObjHead(struct worker *w, struct objhead *oh) { AZ(oh->refcnt); assert(VTAILQ_EMPTY(&oh->objcs)); Lck_Delete(&oh->mtx); - VSL_stats->n_objecthead--; + w->stats->n_objecthead--; free(oh->hash); FREE_OBJ(oh); } @@ -398,7 +398,7 @@ HSH_Drop(struct sess *sp) o->cacheable = 0; if (o->objcore != NULL) /* Pass has no objcore */ HSH_Unbusy(sp); - HSH_Deref(&sp->obj); + HSH_Deref(sp->wrk, &sp->obj); } void @@ -434,7 +434,7 @@ HSH_Unbusy(const struct sess *sp) if (oh != NULL) Lck_Unlock(&oh->mtx); if (parent != NULL) - HSH_Deref(&parent); + HSH_Deref(sp->wrk, &parent); } void @@ -452,7 +452,7 @@ HSH_Ref(struct object *o) } void -HSH_Deref(struct object **oo) +HSH_Deref(struct worker *w, struct object **oo) { struct object *o; struct objhead *oh; @@ -498,7 +498,7 @@ HSH_Deref(struct object **oo) ESI_Destroy(o); HSH_Freestore(o); STV_free(o->objstore); - VSL_stats->n_object--; + w->stats->n_object--; if (oh == NULL) { AZ(oc); @@ -510,7 +510,7 @@ HSH_Deref(struct object **oo) assert(oh->refcnt > 0); if (hash->deref(oh)) return; - HSH_DeleteObjHead(oh); + HSH_DeleteObjHead(w, oh); } void diff --git a/varnish-cache/bin/varnishd/cache_pool.c b/varnish-cache/bin/varnishd/cache_pool.c index 881ba0a6..5c3b363d 100644 --- a/varnish-cache/bin/varnishd/cache_pool.c +++ b/varnish-cache/bin/varnishd/cache_pool.c @@ -98,6 +98,7 @@ static unsigned nthr_max; static pthread_cond_t herder_cond; static struct lock herder_mtx; +static struct lock wstat_mtx; /*-------------------------------------------------------------------- * Write data to fd @@ -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 * wrk_thread(void *priv) { @@ -271,12 +297,16 @@ wrk_thread(void *priv) struct wq *qp; unsigned char wlog[params->shm_workspace]; struct SHA256Context sha256; + struct dstat stats; + unsigned stats_clean = 0; THR_SetName("cache-worker"); w = &ww; CAST_OBJ_NOTNULL(qp, priv, WQ_MAGIC); memset(w, 0, sizeof *w); + memset(&stats, 0, sizeof stats); w->magic = WORKER_MAGIC; + w->stats = &stats; w->lastused = NAN; w->wlb = w->wlp = wlog; w->wle = wlog + sizeof wlog; @@ -299,6 +329,12 @@ wrk_thread(void *priv) if (isnan(w->lastused)) w->lastused = TIM_real(); 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); } if (w->wrq == NULL) @@ -307,14 +343,21 @@ wrk_thread(void *priv) AN(w->wrq); AN(w->wrq->func); w->lastused = NAN; + stats_clean = 0; w->wrq->func(w, w->wrq->priv); AZ(w->wfd); assert(w->wlp == w->wlb); w->wrq = NULL; + if (!Lck_Trylock(&wstat_mtx)) { + wrk_sumstat(w); + stats_clean = 1; + Lck_Unlock(&wstat_mtx); + } Lck_Lock(&qp->mtx); } qp->nthr--; Lck_Unlock(&qp->mtx); + AN(stats_clean); VSL(SLT_WorkThread, 0, "%p end", w); if (w->vcl != NULL) @@ -627,6 +670,7 @@ WRK_Init(void) AZ(pthread_cond_init(&herder_cond, NULL)); Lck_New(&herder_mtx); + Lck_New(&wstat_mtx); wrk_addpools(params->wthread_pools); AZ(pthread_create(&tp, NULL, wrk_herdtimer_thread, NULL)); diff --git a/varnish-cache/bin/varnishd/hash_critbit.c b/varnish-cache/bin/varnishd/hash_critbit.c index 40d77da4..5b3f4fbe 100644 --- a/varnish-cache/bin/varnishd/hash_critbit.c +++ b/varnish-cache/bin/varnishd/hash_critbit.c @@ -345,6 +345,13 @@ hcb_cleaner(void *priv) { struct objhead *oh, *oh2; 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"); (void)priv; @@ -361,10 +368,11 @@ hcb_cleaner(void *priv) fprintf(stderr, "OH %p is cold enough\n", oh); #endif oh->refcnt = 0; - HSH_DeleteObjHead(oh); + HSH_DeleteObjHead(&ww, oh); } } Lck_Unlock(&hcb_mtx); + WRK_SumStat(&ww); } } diff --git a/varnish-cache/bin/varnishd/hash_slinger.h b/varnish-cache/bin/varnishd/hash_slinger.h index 3e96e74f..c52bc4d0 100644 --- a/varnish-cache/bin/varnishd/hash_slinger.h +++ b/varnish-cache/bin/varnishd/hash_slinger.h @@ -50,13 +50,11 @@ struct hash_slinger { /* cache_hash.c */ void HSH_Prealloc(struct sess *sp); -void HSH_DeleteObjHead(struct objhead *oh); void HSH_Freestore(struct object *o); void HSH_Copy(const struct sess *sp, struct objhead *o); struct object *HSH_Lookup(struct sess *sp); void HSH_Unbusy(const struct sess *sp); void HSH_Ref(struct object *o); -void HSH_Deref(struct object **o); void HSH_Drop(struct sess *sp); double HSH_Grace(double g); void HSH_Init(void); @@ -100,4 +98,6 @@ struct objhead { }; 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 */ diff --git a/varnish-cache/include/stat_field.h b/varnish-cache/include/stat_field.h index f5043b4a..ee0c5b33 100644 --- a/varnish-cache/include/stat_field.h +++ b/varnish-cache/include/stat_field.h @@ -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_sess_mem, uint64_t, 0, 'i', "N struct sess_mem") 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_objecthead, uint64_t, 0, 'i', "N struct objecthead") +MAC_STAT(n_object, uint64_t, 1, 'i', "N struct object") +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_frag, uint64_t, 0, 'i', "N small free smf") MAC_STAT(n_smf_large, uint64_t, 0, 'i', "N large free smf")