ref: c3ba64f6935322f09b6de5c2285544fd471c605d
dir: /sys/src/cmd/venti/randtest.c/
#include <u.h> #include <libc.h> #include <venti.h> #include <libsec.h> #include <thread.h> enum { STACK = 32768 }; void xxxsrand(long); long xxxlrand(void); Channel *cw; Channel *cr; char *host; int blocksize, seed, randpct; int doread, dowrite, packets, permute; vlong totalbytes, cur; VtConn *z; int multi; int maxpackets; int sequence; int doublecheck = 1; uint *order; void usage(void) { fprint(2, "usage: randtest [-q] [-h host] [-s seed] [-b blocksize] [-p randpct] [-n totalbytes] [-M maxblocks] [-P] [-r] [-w]\n"); threadexitsall("usage"); } void wr(char *buf, char *buf2) { uchar score[VtScoreSize], score2[VtScoreSize]; DigestState ds; USED(buf2); memset(&ds, 0, sizeof ds); if(doublecheck) sha1((uchar*)buf, blocksize, score, &ds); if(vtwrite(z, score2, VtDataType, (uchar*)buf, blocksize) < 0) sysfatal("vtwrite %V at %,lld: %r", score, cur); if(doublecheck && memcmp(score, score2, VtScoreSize) != 0) sysfatal("score mismatch! %V %V", score, score2); } void wrthread(void *v) { char *p; USED(v); while((p = recvp(cw)) != nil){ wr(p, nil); free(p); } } void rd(char *buf, char *buf2) { uchar score[VtScoreSize]; DigestState ds; memset(&ds, 0, sizeof ds); sha1((uchar*)buf, blocksize, score, &ds); if(vtread(z, score, VtDataType, (uchar*)buf2, blocksize) < 0) sysfatal("vtread %V at %,lld: %r", score, cur); if(memcmp(buf, buf2, blocksize) != 0) sysfatal("bad data read! %V", score); } void rdthread(void *v) { char *p, *buf2; buf2 = vtmalloc(blocksize); USED(v); while((p = recvp(cr)) != nil){ rd(p, buf2); free(p); } } char *template; void run(void (*fn)(char*, char*), Channel *c) { int i, t, j, packets; char *buf2, *buf; buf2 = vtmalloc(blocksize); buf = vtmalloc(blocksize); cur = 0; packets = totalbytes/blocksize; if(maxpackets == 0) maxpackets = packets; order = vtmalloc(packets*sizeof order[0]); for(i=0; i<packets; i++) order[i] = i; if(permute){ for(i=1; i<packets; i++){ j = nrand(i+1); t = order[i]; order[i] = order[j]; order[j] = t; } } for(i=0; i<packets && i<maxpackets; i++){ memmove(buf, template, blocksize); *(uint*)buf = order[i]; if(c){ sendp(c, buf); buf = vtmalloc(blocksize); }else (*fn)(buf, buf2); cur += blocksize; } free(order); } #define TWID64 ((u64int)~(u64int)0) u64int unittoull(char *s) { char *es; u64int n; if(s == nil) return TWID64; n = strtoul(s, &es, 0); if(*es == 'k' || *es == 'K'){ n *= 1024; es++; }else if(*es == 'm' || *es == 'M'){ n *= 1024*1024; es++; }else if(*es == 'g' || *es == 'G'){ n *= 1024*1024*1024; es++; }else if(*es == 't' || *es == 'T'){ n *= 1024*1024; n *= 1024*1024; } if(*es != '\0') return TWID64; return n; } void threadmain(int argc, char *argv[]) { int i, max; vlong t0; double t; blocksize = 8192; seed = 0; randpct = 50; host = nil; doread = 0; dowrite = 0; totalbytes = 1*1024*1024*1024; fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); ARGBEGIN{ case 'b': blocksize = unittoull(EARGF(usage())); break; case 'h': host = EARGF(usage()); break; case 'M': maxpackets = unittoull(EARGF(usage())); break; case 'm': multi = atoi(EARGF(usage())); break; case 'n': totalbytes = unittoull(EARGF(usage())); break; case 'p': randpct = atoi(EARGF(usage())); break; case 'P': permute = 1; break; case 'S': doublecheck = 0; ventidoublechecksha1 = 0; break; case 's': seed = atoi(EARGF(usage())); break; case 'r': doread = 1; break; case 'w': dowrite = 1; break; case 'V': chattyventi++; break; default: usage(); }ARGEND if(doread==0 && dowrite==0){ doread = 1; dowrite = 1; } z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); if(multi){ cr = chancreate(sizeof(void*), 0); cw = chancreate(sizeof(void*), 0); for(i=0; i<multi; i++){ proccreate(wrthread, nil, STACK); proccreate(rdthread, nil, STACK); } } template = vtmalloc(blocksize); xxxsrand(seed); max = (256*randpct)/100; if(max == 0) max = 1; for(i=0; i<blocksize; i++) template[i] = xxxlrand()%max; if(dowrite){ t0 = nsec(); run(wr, cw); for(i=0; i<multi; i++) sendp(cw, nil); t = (nsec() - t0)/1.e9; print("write: %lld bytes / %.3f seconds = %.6f MB/s\n", totalbytes, t, (double)totalbytes/1e6/t); } if(doread){ t0 = nsec(); run(rd, cr); for(i=0; i<multi; i++) sendp(cr, nil); t = (nsec() - t0)/1.e9; print("read: %lld bytes / %.3f seconds = %.6f MB/s\n", totalbytes, t, (double)totalbytes/1e6/t); } threadexitsall(nil); } /* * algorithm by * D. P. Mitchell & J. A. Reeds */ #define LEN 607 #define TAP 273 #define MASK 0x7fffffffL #define A 48271 #define M 2147483647 #define Q 44488 #define R 3399 #define NORM (1.0/(1.0+MASK)) static ulong rng_vec[LEN]; static ulong* rng_tap = rng_vec; static ulong* rng_feed = 0; static void isrand(long seed) { long lo, hi, x; int i; rng_tap = rng_vec; rng_feed = rng_vec+LEN-TAP; seed = seed%M; if(seed < 0) seed += M; if(seed == 0) seed = 89482311; x = seed; /* * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1) */ for(i = -20; i < LEN; i++) { hi = x / Q; lo = x % Q; x = A*lo - R*hi; if(x < 0) x += M; if(i >= 0) rng_vec[i] = x; } } void xxxsrand(long seed) { isrand(seed); } long xxxlrand(void) { ulong x; rng_tap--; if(rng_tap < rng_vec) { if(rng_feed == 0) { isrand(1); rng_tap--; } rng_tap += LEN; } rng_feed--; if(rng_feed < rng_vec) rng_feed += LEN; x = (*rng_feed + *rng_tap) & MASK; *rng_feed = x; return x; }