Blob


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