randtest.c (5704B)
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 && 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; 111 } 112 } 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; 122 } 123 free(order); 124 } 125 126 #define TWID64 ((u64int)~(u64int)0) 127 128 u64int 129 unittoull(char *s) 130 { 131 char *es; 132 u64int n; 133 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; 149 } 150 if(*es != '\0') 151 return TWID64; 152 return n; 153 } 154 155 void 156 threadmain(int argc, char *argv[]) 157 { 158 int i, max; 159 vlong t0; 160 double t; 161 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); 171 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 213 214 if(doread==0 && dowrite==0){ 215 doread = 1; 216 dowrite = 1; 217 } 218 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"); 224 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); 231 } 232 } 233 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); 249 } 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); 258 } 259 threadexitsall(nil); 260 } 261 262 263 /* 264 * algorithm by 265 * D. P. Mitchell & J. A. Reeds 266 */ 267 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)) 276 277 static ulong rng_vec[LEN]; 278 static ulong* rng_tap = rng_vec; 279 static ulong* rng_feed = 0; 280 281 static void 282 isrand(long seed) 283 { 284 long lo, hi, x; 285 int i; 286 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; 306 } 307 } 308 309 void 310 xxxsrand(long seed) 311 { 312 isrand(seed); 313 } 314 315 long 316 xxxlrand(void) 317 { 318 ulong x; 319 320 rng_tap--; 321 if(rng_tap < rng_vec) { 322 if(rng_feed == 0) { 323 isrand(1); 324 rng_tap--; 325 } 326 rng_tap += LEN; 327 } 328 rng_feed--; 329 if(rng_feed < rng_vec) 330 rng_feed += LEN; 331 x = (*rng_feed + *rng_tap) & MASK; 332 *rng_feed = x; 333 334 return x; 335 }