plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }