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 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 }
48 void
49 wrthread(void *v)
50 {
51 char *p;
53 USED(v);
54 while((p = recvp(cw)) != nil){
55 wr(p, nil);
56 free(p);
57 }
58 }
60 void
61 rd(char *buf, char *buf2)
62 {
63 uchar score[VtScoreSize];
64 DigestState ds;
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 }
74 void
75 rdthread(void *v)
76 {
77 char *p, *buf2;
79 buf2 = vtmalloc(blocksize);
80 USED(v);
81 while((p = recvp(cr)) != nil){
82 rd(p, buf2);
83 free(p);
84 }
85 }
87 char *template;
89 void
90 run(void (*fn)(char*, char*), Channel *c)
91 {
92 int i, t, j, packets;
93 char *buf2, *buf;
95 buf2 = vtmalloc(blocksize);
96 buf = vtmalloc(blocksize);
97 cur = 0;
98 packets = totalbytes/blocksize;
99 if(maxpackets > 0 && maxpackets < packets)
100 packets = maxpackets;
101 totalbytes = (vlong)packets * blocksize;
102 order = vtmalloc(packets*sizeof order[0]);
103 for(i=0; i<packets; i++)
104 order[i] = i;
105 if(permute){
106 for(i=1; i<packets; i++){
107 j = nrand(i+1);
108 t = order[i];
109 order[i] = order[j];
110 order[j] = t;
113 for(i=0; i<packets; i++){
114 memmove(buf, template, blocksize);
115 *(uint*)buf = order[i];
116 if(c){
117 sendp(c, buf);
118 buf = vtmalloc(blocksize);
119 }else
120 (*fn)(buf, buf2);
121 cur += blocksize;
123 free(order);
126 #define TWID64 ((u64int)~(u64int)0)
128 u64int
129 unittoull(char *s)
131 char *es;
132 u64int n;
134 if(s == nil)
135 return TWID64;
136 n = strtoul(s, &es, 0);
137 if(*es == 'k' || *es == 'K'){
138 n *= 1024;
139 es++;
140 }else if(*es == 'm' || *es == 'M'){
141 n *= 1024*1024;
142 es++;
143 }else if(*es == 'g' || *es == 'G'){
144 n *= 1024*1024*1024;
145 es++;
146 }else if(*es == 't' || *es == 'T'){
147 n *= 1024*1024;
148 n *= 1024*1024;
150 if(*es != '\0')
151 return TWID64;
152 return n;
155 void
156 threadmain(int argc, char *argv[])
158 int i, max;
159 vlong t0;
160 double t;
162 blocksize = 8192;
163 seed = 0;
164 randpct = 50;
165 host = nil;
166 doread = 0;
167 dowrite = 0;
168 totalbytes = 1*1024*1024*1024;
169 fmtinstall('V', vtscorefmt);
170 fmtinstall('F', vtfcallfmt);
172 ARGBEGIN{
173 case 'b':
174 blocksize = unittoull(EARGF(usage()));
175 break;
176 case 'h':
177 host = EARGF(usage());
178 break;
179 case 'M':
180 maxpackets = unittoull(EARGF(usage()));
181 break;
182 case 'm':
183 multi = atoi(EARGF(usage()));
184 break;
185 case 'n':
186 totalbytes = unittoull(EARGF(usage()));
187 break;
188 case 'p':
189 randpct = atoi(EARGF(usage()));
190 break;
191 case 'P':
192 permute = 1;
193 break;
194 case 'S':
195 doublecheck = 0;
196 ventidoublechecksha1 = 0;
197 break;
198 case 's':
199 seed = atoi(EARGF(usage()));
200 break;
201 case 'r':
202 doread = 1;
203 break;
204 case 'w':
205 dowrite = 1;
206 break;
207 case 'V':
208 chattyventi++;
209 break;
210 default:
211 usage();
212 }ARGEND
214 if(doread==0 && dowrite==0){
215 doread = 1;
216 dowrite = 1;
219 z = vtdial(host);
220 if(z == nil)
221 sysfatal("could not connect to server: %r");
222 if(vtconnect(z) < 0)
223 sysfatal("vtconnect: %r");
225 if(multi){
226 cr = chancreate(sizeof(void*), 0);
227 cw = chancreate(sizeof(void*), 0);
228 for(i=0; i<multi; i++){
229 proccreate(wrthread, nil, STACK);
230 proccreate(rdthread, nil, STACK);
234 template = vtmalloc(blocksize);
235 xxxsrand(seed);
236 max = (256*randpct)/100;
237 if(max == 0)
238 max = 1;
239 for(i=0; i<blocksize; i++)
240 template[i] = xxxlrand()%max;
241 if(dowrite){
242 t0 = nsec();
243 run(wr, cw);
244 for(i=0; i<multi; i++)
245 sendp(cw, nil);
246 t = (nsec() - t0)/1.e9;
247 print("write: %lld bytes / %.3f seconds = %.6f MB/s\n",
248 totalbytes, t, (double)totalbytes/1e6/t);
250 if(doread){
251 t0 = nsec();
252 run(rd, cr);
253 for(i=0; i<multi; i++)
254 sendp(cr, nil);
255 t = (nsec() - t0)/1.e9;
256 print("read: %lld bytes / %.3f seconds = %.6f MB/s\n",
257 totalbytes, t, (double)totalbytes/1e6/t);
259 threadexitsall(nil);
263 /*
264 * algorithm by
265 * D. P. Mitchell & J. A. Reeds
266 */
268 #define LEN 607
269 #define TAP 273
270 #define MASK 0x7fffffffL
271 #define A 48271
272 #define M 2147483647
273 #define Q 44488
274 #define R 3399
275 #define NORM (1.0/(1.0+MASK))
277 static ulong rng_vec[LEN];
278 static ulong* rng_tap = rng_vec;
279 static ulong* rng_feed = 0;
281 static void
282 isrand(long seed)
284 long lo, hi, x;
285 int i;
287 rng_tap = rng_vec;
288 rng_feed = rng_vec+LEN-TAP;
289 seed = seed%M;
290 if(seed < 0)
291 seed += M;
292 if(seed == 0)
293 seed = 89482311;
294 x = seed;
295 /*
296 * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
297 */
298 for(i = -20; i < LEN; i++) {
299 hi = x / Q;
300 lo = x % Q;
301 x = A*lo - R*hi;
302 if(x < 0)
303 x += M;
304 if(i >= 0)
305 rng_vec[i] = x;
309 void
310 xxxsrand(long seed)
312 isrand(seed);
315 long
316 xxxlrand(void)
318 ulong x;
320 rng_tap--;
321 if(rng_tap < rng_vec) {
322 if(rng_feed == 0) {
323 isrand(1);
324 rng_tap--;
326 rng_tap += LEN;
328 rng_feed--;
329 if(rng_feed < rng_vec)
330 rng_feed += LEN;
331 x = (*rng_feed + *rng_tap) & MASK;
332 *rng_feed = x;
334 return x;