1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
4 
5 int collectstats = 1;
6 
7 /* keep in sync with dat.h:/NStat */
8 Statdesc statdesc[NStat] =
9 {
10 	{ "rpc total", },
11 	{ "rpc reads", },
12 	{ "rpc reads ok", },
13 	{ "rpc reads failed", },
14 	{ "rpc read bytes", },
15 	{ "rpc read time", },
16 	{ "rpc read cached", },
17 	{ "rpc read cached time", },
18 	{ "rpc read uncached", },
19 	{ "rpc read uncached time "},
20 
21 	{ "rpc writes", },
22 	{ "rpc writes new", },
23 	{ "rpc writes old", },
24 	{ "rpc writes failed", },
25 	{ "rpc write bytes", },
26 	{ "rpc write time", },
27 	{ "rpc write new time", },
28 	{ "rpc write old time", },
29 
30 	{ "lump cache hits", },
31 	{ "lump cache misses", },
32 	{ "lump cache reads", },
33 	{ "lump cache writes", },
34 	{ "lump cache size", },
35 	{ "lump cache stall", },
36 	{ "lump cache read time", },
37 
38 	{ "disk cache hits", },
39 	{ "disk cache misses", },
40 	{ "disk cache lookups", },
41 	{ "disk cache reads", },
42 	{ "disk cache writes", },
43 	{ "disk cache dirty", },
44 	{ "disk cache size", },
45 	{ "disk cache flushes", },
46 	{ "disk cache stalls", },
47 	{ "disk cache lookup time", },
48 
49 	{ "disk block stalls", },
50 	{ "lump stalls", },
51 
52 	{ "index cache hits", },
53 	{ "index cache misses", },
54 	{ "index cache reads", },
55 	{ "index cache writes", },
56 	{ "index cache fills", },
57 	{ "index cache prefetches", },
58 	{ "index cache dirty", },
59 	{ "index cache size", },
60 	{ "index cache flushes", },
61 	{ "index cache stalls", },
62 	{ "index cache read time", },
63 	{ "index cache lookups" },
64 	{ "index cache summary hits" },
65 	{ "index cache summary prefetches" },
66 
67 	{ "bloom filter hits", },
68 	{ "bloom filter misses", },
69 	{ "bloom filter false misses", },
70 	{ "bloom filter lookups", },
71 	{ "bloom filter ones", },
72 	{ "bloom filter bits", },
73 
74 	{ "arena block reads", },
75 	{ "arena block read bytes", },
76 	{ "arena block writes", },
77 	{ "arena block write bytes", },
78 
79 	{ "isect block reads", },
80 	{ "isect block read bytes", },
81 	{ "isect block writes", },
82 	{ "isect block write bytes", },
83 
84 	{ "sum reads", },
85 	{ "sum read bytes", },
86 
87 	{ "cig loads" },
88 	{ "cig load time" },
89 };
90 
91 QLock statslock;
92 Stats stats;
93 Stats *stathist;
94 int nstathist;
95 ulong statind;
96 ulong stattime;
97 
98 void
statsproc(void * v)99 statsproc(void *v)
100 {
101 	USED(v);
102 
103 	for(;;){
104 		stats.now = time(0);
105 		stathist[stattime%nstathist] = stats;
106 		stattime++;
107 		sleep(1000);
108 	}
109 }
110 
111 void
statsinit(void)112 statsinit(void)
113 {
114 	nstathist = 90000;
115 	stathist = MKNZ(Stats, nstathist);
116 	vtproc(statsproc, nil);
117 }
118 
119 void
setstat(int index,long val)120 setstat(int index, long val)
121 {
122 	qlock(&statslock);
123 	stats.n[index] = val;
124 	qunlock(&statslock);
125 }
126 
127 void
addstat(int index,int inc)128 addstat(int index, int inc)
129 {
130 	if(!collectstats)
131 		return;
132 	qlock(&statslock);
133 	stats.n[index] += inc;
134 	qunlock(&statslock);
135 }
136 
137 void
addstat2(int index,int inc,int index1,int inc1)138 addstat2(int index, int inc, int index1, int inc1)
139 {
140 	if(!collectstats)
141 		return;
142 	qlock(&statslock);
143 	stats.n[index] += inc;
144 	stats.n[index1] += inc1;
145 	qunlock(&statslock);
146 }
147 
148 void
printstats(void)149 printstats(void)
150 {
151 }
152 
153 void
binstats(long (* fn)(Stats * s0,Stats * s1,void * arg),void * arg,long t0,long t1,Statbin * bin,int nbin)154 binstats(long (*fn)(Stats *s0, Stats *s1, void *arg), void *arg,
155 	long t0, long t1, Statbin *bin, int nbin)
156 {
157 	long xt0, t, te, v;
158 	int i, j, lo, hi, m;
159 	vlong tot;
160 	Statbin *b;
161 
162 	t = stats.now;
163 
164 	/* negative times mean relative to now. */
165 	if(t0 <= 0)
166 		t0 += t;
167 	if(t1 <= 0)
168 		t1 += t;
169 	/* ten minute range if none given */
170 	if(t1 <= t0)
171 		t0 = t1 - 60*10;
172 	if(0) fprint(2, "stats %ld-%ld\n", t0, t1);
173 
174 	/* binary search to find t0-1 or close */
175 	lo = stattime;
176 	hi = stattime+nstathist;
177 	while(lo+1 < hi){
178 		m = (lo+hi)/2;
179 		if(stathist[m%nstathist].now >= t0)
180 			hi = m;
181 		else
182 			lo = m;
183 	}
184 	xt0 = stathist[lo%nstathist].now;
185 	if(xt0 >= t1){
186 		/* no samples */
187 		memset(bin, 0, nbin*sizeof bin[0]);
188 		return;
189 	}
190 
191 	hi = stattime+nstathist;
192 	j = lo+1;
193 	for(i=0; i<nbin; i++){
194 		te = t0 + (t1-t0)*i/nbin;
195 		b = &bin[i];
196 		memset(b, 0, sizeof *b);
197 		tot = 0;
198 		for(; j<hi && stathist[j%nstathist].now<te; j++){
199 			v = fn(&stathist[(j-1)%nstathist], &stathist[j%nstathist], arg);
200 			if(b->nsamp==0 || v < b->min)
201 				b->min = v;
202 			if(b->nsamp==0 || v > b->max)
203 				b->max = v;
204 			tot += v;
205 			b->nsamp++;
206 		}
207 		if(b->nsamp)
208 			b->avg = tot / b->nsamp;
209 		if(b->nsamp==0 && i>0)
210 			*b = bin[i-1];
211 	}
212 }
213