aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/venti/randtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/venti/randtest.c')
-rw-r--r--src/cmd/venti/randtest.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/src/cmd/venti/randtest.c b/src/cmd/venti/randtest.c
new file mode 100644
index 00000000..b7a09ef8
--- /dev/null
+++ b/src/cmd/venti/randtest.c
@@ -0,0 +1,334 @@
+#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;
+
+ 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;
+}
+