URI:
       trandtest.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       trandtest.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 }