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 {
/*--------------------------------------------------------------------*/
#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);
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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));
......
......@@ -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);
}
}
......
......@@ -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 */
......@@ -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")
......
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