aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/venti/srv/stats.c
blob: 874f7d27065398e0d6277cd5d18d54f235ba856c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#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", },

	{ "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", },
};

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 t, xt0, te, v;
	int i, j, lo, hi, m, oj;
	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(0) fprint(2, "bsearch found %ld\n", xt0);
	if(xt0 >= t1){
		/* no samples */
		memset(bin, 0, nbin*sizeof bin[0]);
		return;
	}

	hi = stattime+nstathist;
	te = t0;
	j = lo+1;
	for(i=0; i<nbin; i++){
		t = te;
		te = t0 + (t1-t0)*i/nbin;
		b = &bin[i];
		memset(b, 0, sizeof *b);
		tot = 0;
		oj = j;
		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(0) fprint(2, "bin%d: %ld to %ld; %d to %d - %d samples\n", i, t, te, oj, j, b->nsamp);
		if(b->nsamp)
			b->avg = tot / b->nsamp;
		if(b->nsamp==0 && i>0)
			*b = bin[i-1];
	}	
}