Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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