#include "stdinc.h"
#include "dat.h"
#include "fns.h"
int collectstats = 1;
/* keep in sync with dat.h:/NStat */
Statdesc statdesc[NStat] =
{
{ "rpc total", },
{ "rpc reads", },
{ "rpc reads ok", },
{ "rpc reads failed", },
{ "rpc read bytes", },
{ "rpc read time", },
{ "rpc read cached", },
{ "rpc read cached time", },
{ "rpc read uncached", },
{ "rpc read uncached time "},
{ "rpc writes", },
{ "rpc writes new", },
{ "rpc writes old", },
{ "rpc writes failed", },
{ "rpc write bytes", },
{ "rpc write time", },
{ "rpc write new time", },
{ "rpc write old time", },
{ "lump cache hits", },
{ "lump cache misses", },
{ "lump cache reads", },
{ "lump cache writes", },
{ "lump cache size", },
{ "lump cache stall", },
{ "lump cache read time", },
{ "disk cache hits", },
{ "disk cache misses", },
{ "disk cache lookups", },
{ "disk cache reads", },
{ "disk cache writes", },
{ "disk cache dirty", },
{ "disk cache size", },
{ "disk cache flushes", },
{ "disk cache stalls", },
{ "disk cache lookup time", },
{ "disk block stalls", },
{ "lump stalls", },
{ "index cache hits", },
{ "index cache misses", },
{ "index cache reads", },
{ "index cache writes", },
{ "index cache fills", },
{ "index cache prefetches", },
{ "index cache dirty", },
{ "index cache size", },
{ "index cache flushes", },
{ "index cache stalls", },
{ "index cache read time", },
{ "index cache lookups" },
{ "index cache summary hits" },
{ "index cache summary prefetches" },
{ "bloom filter hits", },
{ "bloom filter misses", },
{ "bloom filter false misses", },
{ "bloom filter lookups", },
{ "bloom filter ones", },
{ "bloom filter bits", },
{ "bloom filter lookup time", },
{ "arena block reads", },
{ "arena block read bytes", },
{ "arena block writes", },
{ "arena block write bytes", },
{ "isect block reads", },
{ "isect block read bytes", },
{ "isect block writes", },
{ "isect block write bytes", },
{ "sum reads", },
{ "sum read bytes", },
{ "cig loads" },
{ "cig load time" },
};
QLock statslock;
Stats stats;
Stats *stathist;
int nstathist;
ulong statind;
ulong stattime;
void
statsproc(void *v)
{
USED(v);
for(;;){
stats.now = time(0);
stathist[stattime%nstathist] = stats;
stattime++;
sleep(1000);
}
}
void
statsinit(void)
{
nstathist = 90000;
stathist = MKNZ(Stats, nstathist);
vtproc(statsproc, nil);
}
void
setstat(int index, long val)
{
qlock(&statslock);
stats.n[index] = val;
qunlock(&statslock);
}
void
addstat(int index, int inc)
{
if(!collectstats)
return;
qlock(&statslock);
stats.n[index] += inc;
qunlock(&statslock);
}
void
addstat2(int index, int inc, int index1, int inc1)
{
if(!collectstats)
return;
qlock(&statslock);
stats.n[index] += inc;
stats.n[index1] += inc1;
qunlock(&statslock);
}
void
printstats(void)
{
}
void
binstats(long (*fn)(Stats *s0, Stats *s1, void *arg), void *arg,
long t0, long t1, Statbin *bin, int nbin)
{
long xt0, t, te, v;
int i, j, lo, hi, m;
vlong tot;
Statbin *b;
t = stats.now;
/* negative times mean relative to now. */
if(t0 <= 0)
t0 += t;
if(t1 <= 0)
t1 += t;
/* ten minute range if none given */
if(t1 <= t0)
t0 = t1 - 60*10;
if(0) fprint(2, "stats %ld-%ld\n", t0, t1);
/* binary search to find t0-1 or close */
lo = stattime;
hi = stattime+nstathist;
while(lo+1 < hi){
m = (lo+hi)/2;
if(stathist[m%nstathist].now >= t0)
hi = m;
else
lo = m;
}
xt0 = stathist[lo%nstathist].now;
if(xt0 >= t1){
/* no samples */
memset(bin, 0, nbin*sizeof bin[0]);
return;
}
hi = stattime+nstathist;
j = lo+1;
for(i=0; i<nbin; i++){
te = t0 + (t1-t0)*i/nbin;
b = &bin[i];
memset(b, 0, sizeof *b);
tot = 0;
for(; j<hi && stathist[j%nstathist].now<te; j++){
v = fn(&stathist[(j-1)%nstathist], &stathist[j%nstathist], arg);
if(b->nsamp==0 || v < b->min)
b->min = v;
if(b->nsamp==0 || v > b->max)
b->max = v;
tot += v;
b->nsamp++;
}
if(b->nsamp)
b->avg = tot / b->nsamp;
if(b->nsamp==0 && i>0)
*b = bin[i-1];
}
}
|