]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/venti/randtest.c
cwfs: fix listen filedescriptor leaks
[plan9front.git] / sys / src / cmd / venti / randtest.c
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