335 lines · 5.5 KB · C
RawDownload
#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; voidusage(void){	fprint(2, "usage: randtest [-q] [-h host] [-s seed] [-b blocksize] [-p randpct] [-n totalbytes] [-M maxblocks] [-P] [-r] [-w]\n");	threadexitsall("usage");} voidwr(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);} voidwrthread(void *v){	char *p; 	USED(v);	while((p = recvp(cw)) != nil){		wr(p, nil);		free(p);	}} voidrd(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);} voidrdthread(void *v){	char *p, *buf2; 	buf2 = vtmalloc(blocksize);	USED(v);	while((p = recvp(cr)) != nil){		rd(p, buf2);		free(p);	}} char *template; voidrun(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) u64intunittoull(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;} voidthreadmain(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 voidisrand(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;	}} voidxxxsrand(long seed){	isrand(seed);} longxxxlrand(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;}