xref: /plan9/sys/src/cmd/venti/randtest.c (revision 368c31ab13393dea083228fdd1c3445076f83a4b)
1*368c31abSDavid du Colombier #include <u.h>
2*368c31abSDavid du Colombier #include <libc.h>
3*368c31abSDavid du Colombier #include <venti.h>
4*368c31abSDavid du Colombier #include <libsec.h>
5*368c31abSDavid du Colombier #include <thread.h>
6*368c31abSDavid du Colombier 
7*368c31abSDavid du Colombier 
8*368c31abSDavid du Colombier enum { STACK = 32768 };
9*368c31abSDavid du Colombier void xxxsrand(long);
10*368c31abSDavid du Colombier long xxxlrand(void);
11*368c31abSDavid du Colombier 
12*368c31abSDavid du Colombier Channel *cw;
13*368c31abSDavid du Colombier Channel *cr;
14*368c31abSDavid du Colombier char *host;
15*368c31abSDavid du Colombier int blocksize, seed, randpct;
16*368c31abSDavid du Colombier int doread, dowrite, packets, permute;
17*368c31abSDavid du Colombier vlong totalbytes, cur;
18*368c31abSDavid du Colombier VtConn *z;
19*368c31abSDavid du Colombier int multi;
20*368c31abSDavid du Colombier int maxpackets;
21*368c31abSDavid du Colombier int sequence;
22*368c31abSDavid du Colombier int doublecheck = 1;
23*368c31abSDavid du Colombier uint *order;
24*368c31abSDavid du Colombier 
25*368c31abSDavid du Colombier void
usage(void)26*368c31abSDavid du Colombier usage(void)
27*368c31abSDavid du Colombier {
28*368c31abSDavid du Colombier 	fprint(2, "usage: randtest [-q] [-h host] [-s seed] [-b blocksize] [-p randpct] [-n totalbytes] [-M maxblocks] [-P] [-r] [-w]\n");
29*368c31abSDavid du Colombier 	threadexitsall("usage");
30*368c31abSDavid du Colombier }
31*368c31abSDavid du Colombier 
32*368c31abSDavid du Colombier void
wr(char * buf,char * buf2)33*368c31abSDavid du Colombier wr(char *buf, char *buf2)
34*368c31abSDavid du Colombier {
35*368c31abSDavid du Colombier 	uchar score[VtScoreSize], score2[VtScoreSize];
36*368c31abSDavid du Colombier 	DigestState ds;
37*368c31abSDavid du Colombier 
38*368c31abSDavid du Colombier 	USED(buf2);
39*368c31abSDavid du Colombier 	memset(&ds, 0, sizeof ds);
40*368c31abSDavid du Colombier 	if(doublecheck)
41*368c31abSDavid du Colombier 		sha1((uchar*)buf, blocksize, score, &ds);
42*368c31abSDavid du Colombier 	if(vtwrite(z, score2, VtDataType, (uchar*)buf, blocksize) < 0)
43*368c31abSDavid du Colombier 		sysfatal("vtwrite %V at %,lld: %r", score, cur);
44*368c31abSDavid du Colombier 	if(doublecheck && memcmp(score, score2, VtScoreSize) != 0)
45*368c31abSDavid du Colombier 		sysfatal("score mismatch! %V %V", score, score2);
46*368c31abSDavid du Colombier }
47*368c31abSDavid du Colombier 
48*368c31abSDavid du Colombier void
wrthread(void * v)49*368c31abSDavid du Colombier wrthread(void *v)
50*368c31abSDavid du Colombier {
51*368c31abSDavid du Colombier 	char *p;
52*368c31abSDavid du Colombier 
53*368c31abSDavid du Colombier 	USED(v);
54*368c31abSDavid du Colombier 	while((p = recvp(cw)) != nil){
55*368c31abSDavid du Colombier 		wr(p, nil);
56*368c31abSDavid du Colombier 		free(p);
57*368c31abSDavid du Colombier 	}
58*368c31abSDavid du Colombier }
59*368c31abSDavid du Colombier 
60*368c31abSDavid du Colombier void
rd(char * buf,char * buf2)61*368c31abSDavid du Colombier rd(char *buf, char *buf2)
62*368c31abSDavid du Colombier {
63*368c31abSDavid du Colombier 	uchar score[VtScoreSize];
64*368c31abSDavid du Colombier 	DigestState ds;
65*368c31abSDavid du Colombier 
66*368c31abSDavid du Colombier 	memset(&ds, 0, sizeof ds);
67*368c31abSDavid du Colombier 	sha1((uchar*)buf, blocksize, score, &ds);
68*368c31abSDavid du Colombier 	if(vtread(z, score, VtDataType, (uchar*)buf2, blocksize) < 0)
69*368c31abSDavid du Colombier 		sysfatal("vtread %V at %,lld: %r", score, cur);
70*368c31abSDavid du Colombier 	if(memcmp(buf, buf2, blocksize) != 0)
71*368c31abSDavid du Colombier 		sysfatal("bad data read! %V", score);
72*368c31abSDavid du Colombier }
73*368c31abSDavid du Colombier 
74*368c31abSDavid du Colombier void
rdthread(void * v)75*368c31abSDavid du Colombier rdthread(void *v)
76*368c31abSDavid du Colombier {
77*368c31abSDavid du Colombier 	char *p, *buf2;
78*368c31abSDavid du Colombier 
79*368c31abSDavid du Colombier 	buf2 = vtmalloc(blocksize);
80*368c31abSDavid du Colombier 	USED(v);
81*368c31abSDavid du Colombier 	while((p = recvp(cr)) != nil){
82*368c31abSDavid du Colombier 		rd(p, buf2);
83*368c31abSDavid du Colombier 		free(p);
84*368c31abSDavid du Colombier 	}
85*368c31abSDavid du Colombier }
86*368c31abSDavid du Colombier 
87*368c31abSDavid du Colombier char *template;
88*368c31abSDavid du Colombier 
89*368c31abSDavid du Colombier void
run(void (* fn)(char *,char *),Channel * c)90*368c31abSDavid du Colombier run(void (*fn)(char*, char*), Channel *c)
91*368c31abSDavid du Colombier {
92*368c31abSDavid du Colombier 	int i, t, j, packets;
93*368c31abSDavid du Colombier 	char *buf2, *buf;
94*368c31abSDavid du Colombier 
95*368c31abSDavid du Colombier 	buf2 = vtmalloc(blocksize);
96*368c31abSDavid du Colombier 	buf = vtmalloc(blocksize);
97*368c31abSDavid du Colombier 	cur = 0;
98*368c31abSDavid du Colombier 	packets = totalbytes/blocksize;
99*368c31abSDavid du Colombier 	if(maxpackets == 0)
100*368c31abSDavid du Colombier 		maxpackets = packets;
101*368c31abSDavid du Colombier 	order = vtmalloc(packets*sizeof order[0]);
102*368c31abSDavid du Colombier 	for(i=0; i<packets; i++)
103*368c31abSDavid du Colombier 		order[i] = i;
104*368c31abSDavid du Colombier 	if(permute){
105*368c31abSDavid du Colombier 		for(i=1; i<packets; i++){
106*368c31abSDavid du Colombier 			j = nrand(i+1);
107*368c31abSDavid du Colombier 			t = order[i];
108*368c31abSDavid du Colombier 			order[i] = order[j];
109*368c31abSDavid du Colombier 			order[j] = t;
110*368c31abSDavid du Colombier 		}
111*368c31abSDavid du Colombier 	}
112*368c31abSDavid du Colombier 	for(i=0; i<packets && i<maxpackets; i++){
113*368c31abSDavid du Colombier 		memmove(buf, template, blocksize);
114*368c31abSDavid du Colombier 		*(uint*)buf = order[i];
115*368c31abSDavid du Colombier 		if(c){
116*368c31abSDavid du Colombier 			sendp(c, buf);
117*368c31abSDavid du Colombier 			buf = vtmalloc(blocksize);
118*368c31abSDavid du Colombier 		}else
119*368c31abSDavid du Colombier 			(*fn)(buf, buf2);
120*368c31abSDavid du Colombier 		cur += blocksize;
121*368c31abSDavid du Colombier 	}
122*368c31abSDavid du Colombier 	free(order);
123*368c31abSDavid du Colombier }
124*368c31abSDavid du Colombier 
125*368c31abSDavid du Colombier #define TWID64	((u64int)~(u64int)0)
126*368c31abSDavid du Colombier 
127*368c31abSDavid du Colombier u64int
unittoull(char * s)128*368c31abSDavid du Colombier unittoull(char *s)
129*368c31abSDavid du Colombier {
130*368c31abSDavid du Colombier 	char *es;
131*368c31abSDavid du Colombier 	u64int n;
132*368c31abSDavid du Colombier 
133*368c31abSDavid du Colombier 	if(s == nil)
134*368c31abSDavid du Colombier 		return TWID64;
135*368c31abSDavid du Colombier 	n = strtoul(s, &es, 0);
136*368c31abSDavid du Colombier 	if(*es == 'k' || *es == 'K'){
137*368c31abSDavid du Colombier 		n *= 1024;
138*368c31abSDavid du Colombier 		es++;
139*368c31abSDavid du Colombier 	}else if(*es == 'm' || *es == 'M'){
140*368c31abSDavid du Colombier 		n *= 1024*1024;
141*368c31abSDavid du Colombier 		es++;
142*368c31abSDavid du Colombier 	}else if(*es == 'g' || *es == 'G'){
143*368c31abSDavid du Colombier 		n *= 1024*1024*1024;
144*368c31abSDavid du Colombier 		es++;
145*368c31abSDavid du Colombier 	}else if(*es == 't' || *es == 'T'){
146*368c31abSDavid du Colombier 		n *= 1024*1024;
147*368c31abSDavid du Colombier 		n *= 1024*1024;
148*368c31abSDavid du Colombier 	}
149*368c31abSDavid du Colombier 	if(*es != '\0')
150*368c31abSDavid du Colombier 		return TWID64;
151*368c31abSDavid du Colombier 	return n;
152*368c31abSDavid du Colombier }
153*368c31abSDavid du Colombier 
154*368c31abSDavid du Colombier void
threadmain(int argc,char * argv[])155*368c31abSDavid du Colombier threadmain(int argc, char *argv[])
156*368c31abSDavid du Colombier {
157*368c31abSDavid du Colombier 	int i, max;
158*368c31abSDavid du Colombier 	vlong t0;
159*368c31abSDavid du Colombier 	double t;
160*368c31abSDavid du Colombier 
161*368c31abSDavid du Colombier 	blocksize = 8192;
162*368c31abSDavid du Colombier 	seed = 0;
163*368c31abSDavid du Colombier 	randpct = 50;
164*368c31abSDavid du Colombier 	host = nil;
165*368c31abSDavid du Colombier 	doread = 0;
166*368c31abSDavid du Colombier 	dowrite = 0;
167*368c31abSDavid du Colombier 	totalbytes = 1*1024*1024*1024;
168*368c31abSDavid du Colombier 	fmtinstall('V', vtscorefmt);
169*368c31abSDavid du Colombier 	fmtinstall('F', vtfcallfmt);
170*368c31abSDavid du Colombier 
171*368c31abSDavid du Colombier 	ARGBEGIN{
172*368c31abSDavid du Colombier 	case 'b':
173*368c31abSDavid du Colombier 		blocksize = unittoull(EARGF(usage()));
174*368c31abSDavid du Colombier 		break;
175*368c31abSDavid du Colombier 	case 'h':
176*368c31abSDavid du Colombier 		host = EARGF(usage());
177*368c31abSDavid du Colombier 		break;
178*368c31abSDavid du Colombier 	case 'M':
179*368c31abSDavid du Colombier 		maxpackets = unittoull(EARGF(usage()));
180*368c31abSDavid du Colombier 		break;
181*368c31abSDavid du Colombier 	case 'm':
182*368c31abSDavid du Colombier 		multi = atoi(EARGF(usage()));
183*368c31abSDavid du Colombier 		break;
184*368c31abSDavid du Colombier 	case 'n':
185*368c31abSDavid du Colombier 		totalbytes = unittoull(EARGF(usage()));
186*368c31abSDavid du Colombier 		break;
187*368c31abSDavid du Colombier 	case 'p':
188*368c31abSDavid du Colombier 		randpct = atoi(EARGF(usage()));
189*368c31abSDavid du Colombier 		break;
190*368c31abSDavid du Colombier 	case 'P':
191*368c31abSDavid du Colombier 		permute = 1;
192*368c31abSDavid du Colombier 		break;
193*368c31abSDavid du Colombier 	case 'S':
194*368c31abSDavid du Colombier 		doublecheck = 0;
195*368c31abSDavid du Colombier 		ventidoublechecksha1 = 0;
196*368c31abSDavid du Colombier 		break;
197*368c31abSDavid du Colombier 	case 's':
198*368c31abSDavid du Colombier 		seed = atoi(EARGF(usage()));
199*368c31abSDavid du Colombier 		break;
200*368c31abSDavid du Colombier 	case 'r':
201*368c31abSDavid du Colombier 		doread = 1;
202*368c31abSDavid du Colombier 		break;
203*368c31abSDavid du Colombier 	case 'w':
204*368c31abSDavid du Colombier 		dowrite = 1;
205*368c31abSDavid du Colombier 		break;
206*368c31abSDavid du Colombier 	case 'V':
207*368c31abSDavid du Colombier 		chattyventi++;
208*368c31abSDavid du Colombier 		break;
209*368c31abSDavid du Colombier 	default:
210*368c31abSDavid du Colombier 		usage();
211*368c31abSDavid du Colombier 	}ARGEND
212*368c31abSDavid du Colombier 
213*368c31abSDavid du Colombier 	if(doread==0 && dowrite==0){
214*368c31abSDavid du Colombier 		doread = 1;
215*368c31abSDavid du Colombier 		dowrite = 1;
216*368c31abSDavid du Colombier 	}
217*368c31abSDavid du Colombier 
218*368c31abSDavid du Colombier 	z = vtdial(host);
219*368c31abSDavid du Colombier 	if(z == nil)
220*368c31abSDavid du Colombier 		sysfatal("could not connect to server: %r");
221*368c31abSDavid du Colombier 	if(vtconnect(z) < 0)
222*368c31abSDavid du Colombier 		sysfatal("vtconnect: %r");
223*368c31abSDavid du Colombier 
224*368c31abSDavid du Colombier 	if(multi){
225*368c31abSDavid du Colombier 		cr = chancreate(sizeof(void*), 0);
226*368c31abSDavid du Colombier 		cw = chancreate(sizeof(void*), 0);
227*368c31abSDavid du Colombier 		for(i=0; i<multi; i++){
228*368c31abSDavid du Colombier 			proccreate(wrthread, nil, STACK);
229*368c31abSDavid du Colombier 			proccreate(rdthread, nil, STACK);
230*368c31abSDavid du Colombier 		}
231*368c31abSDavid du Colombier 	}
232*368c31abSDavid du Colombier 
233*368c31abSDavid du Colombier 	template = vtmalloc(blocksize);
234*368c31abSDavid du Colombier 	xxxsrand(seed);
235*368c31abSDavid du Colombier 	max = (256*randpct)/100;
236*368c31abSDavid du Colombier 	if(max == 0)
237*368c31abSDavid du Colombier 		max = 1;
238*368c31abSDavid du Colombier 	for(i=0; i<blocksize; i++)
239*368c31abSDavid du Colombier 		template[i] = xxxlrand()%max;
240*368c31abSDavid du Colombier 	if(dowrite){
241*368c31abSDavid du Colombier 		t0 = nsec();
242*368c31abSDavid du Colombier 		run(wr, cw);
243*368c31abSDavid du Colombier 		for(i=0; i<multi; i++)
244*368c31abSDavid du Colombier 			sendp(cw, nil);
245*368c31abSDavid du Colombier 		t = (nsec() - t0)/1.e9;
246*368c31abSDavid du Colombier 		print("write: %lld bytes / %.3f seconds = %.6f MB/s\n",
247*368c31abSDavid du Colombier 			totalbytes, t, (double)totalbytes/1e6/t);
248*368c31abSDavid du Colombier 	}
249*368c31abSDavid du Colombier 	if(doread){
250*368c31abSDavid du Colombier 		t0 = nsec();
251*368c31abSDavid du Colombier 		run(rd, cr);
252*368c31abSDavid du Colombier 		for(i=0; i<multi; i++)
253*368c31abSDavid du Colombier 			sendp(cr, nil);
254*368c31abSDavid du Colombier 		t = (nsec() - t0)/1.e9;
255*368c31abSDavid du Colombier 		print("read: %lld bytes / %.3f seconds = %.6f MB/s\n",
256*368c31abSDavid du Colombier 			totalbytes, t, (double)totalbytes/1e6/t);
257*368c31abSDavid du Colombier 	}
258*368c31abSDavid du Colombier 	threadexitsall(nil);
259*368c31abSDavid du Colombier }
260*368c31abSDavid du Colombier 
261*368c31abSDavid du Colombier 
262*368c31abSDavid du Colombier /*
263*368c31abSDavid du Colombier  *	algorithm by
264*368c31abSDavid du Colombier  *	D. P. Mitchell & J. A. Reeds
265*368c31abSDavid du Colombier  */
266*368c31abSDavid du Colombier 
267*368c31abSDavid du Colombier #define	LEN	607
268*368c31abSDavid du Colombier #define	TAP	273
269*368c31abSDavid du Colombier #define	MASK	0x7fffffffL
270*368c31abSDavid du Colombier #define	A	48271
271*368c31abSDavid du Colombier #define	M	2147483647
272*368c31abSDavid du Colombier #define	Q	44488
273*368c31abSDavid du Colombier #define	R	3399
274*368c31abSDavid du Colombier #define	NORM	(1.0/(1.0+MASK))
275*368c31abSDavid du Colombier 
276*368c31abSDavid du Colombier static	ulong	rng_vec[LEN];
277*368c31abSDavid du Colombier static	ulong*	rng_tap = rng_vec;
278*368c31abSDavid du Colombier static	ulong*	rng_feed = 0;
279*368c31abSDavid du Colombier 
280*368c31abSDavid du Colombier static void
isrand(long seed)281*368c31abSDavid du Colombier isrand(long seed)
282*368c31abSDavid du Colombier {
283*368c31abSDavid du Colombier 	long lo, hi, x;
284*368c31abSDavid du Colombier 	int i;
285*368c31abSDavid du Colombier 
286*368c31abSDavid du Colombier 	rng_tap = rng_vec;
287*368c31abSDavid du Colombier 	rng_feed = rng_vec+LEN-TAP;
288*368c31abSDavid du Colombier 	seed = seed%M;
289*368c31abSDavid du Colombier 	if(seed < 0)
290*368c31abSDavid du Colombier 		seed += M;
291*368c31abSDavid du Colombier 	if(seed == 0)
292*368c31abSDavid du Colombier 		seed = 89482311;
293*368c31abSDavid du Colombier 	x = seed;
294*368c31abSDavid du Colombier 	/*
295*368c31abSDavid du Colombier 	 *	Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
296*368c31abSDavid du Colombier 	 */
297*368c31abSDavid du Colombier 	for(i = -20; i < LEN; i++) {
298*368c31abSDavid du Colombier 		hi = x / Q;
299*368c31abSDavid du Colombier 		lo = x % Q;
300*368c31abSDavid du Colombier 		x = A*lo - R*hi;
301*368c31abSDavid du Colombier 		if(x < 0)
302*368c31abSDavid du Colombier 			x += M;
303*368c31abSDavid du Colombier 		if(i >= 0)
304*368c31abSDavid du Colombier 			rng_vec[i] = x;
305*368c31abSDavid du Colombier 	}
306*368c31abSDavid du Colombier }
307*368c31abSDavid du Colombier 
308*368c31abSDavid du Colombier void
xxxsrand(long seed)309*368c31abSDavid du Colombier xxxsrand(long seed)
310*368c31abSDavid du Colombier {
311*368c31abSDavid du Colombier 	isrand(seed);
312*368c31abSDavid du Colombier }
313*368c31abSDavid du Colombier 
314*368c31abSDavid du Colombier long
xxxlrand(void)315*368c31abSDavid du Colombier xxxlrand(void)
316*368c31abSDavid du Colombier {
317*368c31abSDavid du Colombier 	ulong x;
318*368c31abSDavid du Colombier 
319*368c31abSDavid du Colombier 	rng_tap--;
320*368c31abSDavid du Colombier 	if(rng_tap < rng_vec) {
321*368c31abSDavid du Colombier 		if(rng_feed == 0) {
322*368c31abSDavid du Colombier 			isrand(1);
323*368c31abSDavid du Colombier 			rng_tap--;
324*368c31abSDavid du Colombier 		}
325*368c31abSDavid du Colombier 		rng_tap += LEN;
326*368c31abSDavid du Colombier 	}
327*368c31abSDavid du Colombier 	rng_feed--;
328*368c31abSDavid du Colombier 	if(rng_feed < rng_vec)
329*368c31abSDavid du Colombier 		rng_feed += LEN;
330*368c31abSDavid du Colombier 	x = (*rng_feed + *rng_tap) & MASK;
331*368c31abSDavid du Colombier 	*rng_feed = x;
332*368c31abSDavid du Colombier 
333*368c31abSDavid du Colombier 	return x;
334*368c31abSDavid du Colombier }
335*368c31abSDavid du Colombier 
336