randtest.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <venti.h>
  12. #include <libsec.h>
  13. #include <thread.h>
  14. enum { STACK = 32768 };
  15. void xxxsrand(int32_t);
  16. int32_t xxxlrand(void);
  17. Channel *cw;
  18. Channel *cr;
  19. char *host;
  20. int blocksize, seed, randpct;
  21. int doread, dowrite, packets, permute;
  22. int64_t totalbytes, cur;
  23. VtConn *z;
  24. int multi;
  25. int maxpackets;
  26. int sequence;
  27. int doublecheck = 1;
  28. uint *order;
  29. void
  30. usage(void)
  31. {
  32. fprint(2, "usage: randtest [-q] [-h host] [-s seed] [-b blocksize] [-p randpct] [-n totalbytes] [-M maxblocks] [-P] [-r] [-w]\n");
  33. threadexitsall("usage");
  34. }
  35. void
  36. wr(char *buf, char *buf2)
  37. {
  38. uint8_t score[VtScoreSize], score2[VtScoreSize];
  39. DigestState ds;
  40. USED(buf2);
  41. memset(&ds, 0, sizeof ds);
  42. if(doublecheck)
  43. sha1((uint8_t*)buf, blocksize, score, &ds);
  44. if(vtwrite(z, score2, VtDataType, (uint8_t*)buf, blocksize) < 0)
  45. sysfatal("vtwrite %V at %,lld: %r", score, cur);
  46. if(doublecheck && memcmp(score, score2, VtScoreSize) != 0)
  47. sysfatal("score mismatch! %V %V", score, score2);
  48. }
  49. void
  50. wrthread(void *v)
  51. {
  52. char *p;
  53. USED(v);
  54. while((p = recvp(cw)) != nil){
  55. wr(p, nil);
  56. free(p);
  57. }
  58. }
  59. void
  60. rd(char *buf, char *buf2)
  61. {
  62. uint8_t score[VtScoreSize];
  63. DigestState ds;
  64. memset(&ds, 0, sizeof ds);
  65. sha1((uint8_t*)buf, blocksize, score, &ds);
  66. if(vtread(z, score, VtDataType, (uint8_t*)buf2, blocksize) < 0)
  67. sysfatal("vtread %V at %,lld: %r", score, cur);
  68. if(memcmp(buf, buf2, blocksize) != 0)
  69. sysfatal("bad data read! %V", score);
  70. }
  71. void
  72. rdthread(void *v)
  73. {
  74. char *p, *buf2;
  75. buf2 = vtmalloc(blocksize);
  76. USED(v);
  77. while((p = recvp(cr)) != nil){
  78. rd(p, buf2);
  79. free(p);
  80. }
  81. }
  82. char *template;
  83. void
  84. run(void (*fn)(char*, char*), Channel *c)
  85. {
  86. int i, t, j, packets;
  87. char *buf2, *buf;
  88. buf2 = vtmalloc(blocksize);
  89. buf = vtmalloc(blocksize);
  90. cur = 0;
  91. packets = totalbytes/blocksize;
  92. if(maxpackets == 0)
  93. maxpackets = packets;
  94. order = vtmalloc(packets*sizeof order[0]);
  95. for(i=0; i<packets; i++)
  96. order[i] = i;
  97. if(permute){
  98. for(i=1; i<packets; i++){
  99. j = nrand(i+1);
  100. t = order[i];
  101. order[i] = order[j];
  102. order[j] = t;
  103. }
  104. }
  105. for(i=0; i<packets && i<maxpackets; i++){
  106. memmove(buf, template, blocksize);
  107. *(uint*)buf = order[i];
  108. if(c){
  109. sendp(c, buf);
  110. buf = vtmalloc(blocksize);
  111. }else
  112. (*fn)(buf, buf2);
  113. cur += blocksize;
  114. }
  115. free(order);
  116. }
  117. #define TWID64 ((uint64_t)~(uint64_t)0)
  118. uint64_t
  119. unittoull(char *s)
  120. {
  121. char *es;
  122. uint64_t n;
  123. if(s == nil)
  124. return TWID64;
  125. n = strtoul(s, &es, 0);
  126. if(*es == 'k' || *es == 'K'){
  127. n *= 1024;
  128. es++;
  129. }else if(*es == 'm' || *es == 'M'){
  130. n *= 1024*1024;
  131. es++;
  132. }else if(*es == 'g' || *es == 'G'){
  133. n *= 1024*1024*1024;
  134. es++;
  135. }else if(*es == 't' || *es == 'T'){
  136. n *= 1024*1024;
  137. n *= 1024*1024;
  138. }
  139. if(*es != '\0')
  140. return TWID64;
  141. return n;
  142. }
  143. void
  144. threadmain(int argc, char *argv[])
  145. {
  146. int i, max;
  147. vlong t0;
  148. double t;
  149. blocksize = 8192;
  150. seed = 0;
  151. randpct = 50;
  152. host = nil;
  153. doread = 0;
  154. dowrite = 0;
  155. totalbytes = 1*1024*1024*1024;
  156. fmtinstall('V', vtscorefmt);
  157. fmtinstall('F', vtfcallfmt);
  158. ARGBEGIN{
  159. case 'b':
  160. blocksize = unittoull(EARGF(usage()));
  161. break;
  162. case 'h':
  163. host = EARGF(usage());
  164. break;
  165. case 'M':
  166. maxpackets = unittoull(EARGF(usage()));
  167. break;
  168. case 'm':
  169. multi = atoi(EARGF(usage()));
  170. break;
  171. case 'n':
  172. totalbytes = unittoull(EARGF(usage()));
  173. break;
  174. case 'p':
  175. randpct = atoi(EARGF(usage()));
  176. break;
  177. case 'P':
  178. permute = 1;
  179. break;
  180. case 'S':
  181. doublecheck = 0;
  182. ventidoublechecksha1 = 0;
  183. break;
  184. case 's':
  185. seed = atoi(EARGF(usage()));
  186. break;
  187. case 'r':
  188. doread = 1;
  189. break;
  190. case 'w':
  191. dowrite = 1;
  192. break;
  193. case 'V':
  194. chattyventi++;
  195. break;
  196. default:
  197. usage();
  198. }ARGEND
  199. if(doread==0 && dowrite==0){
  200. doread = 1;
  201. dowrite = 1;
  202. }
  203. z = vtdial(host);
  204. if(z == nil)
  205. sysfatal("could not connect to server: %r");
  206. if(vtconnect(z) < 0)
  207. sysfatal("vtconnect: %r");
  208. if(multi){
  209. cr = chancreate(sizeof(void*), 0);
  210. cw = chancreate(sizeof(void*), 0);
  211. for(i=0; i<multi; i++){
  212. proccreate(wrthread, nil, STACK);
  213. proccreate(rdthread, nil, STACK);
  214. }
  215. }
  216. template = vtmalloc(blocksize);
  217. xxxsrand(seed);
  218. max = (256*randpct)/100;
  219. if(max == 0)
  220. max = 1;
  221. for(i=0; i<blocksize; i++)
  222. template[i] = xxxlrand()%max;
  223. if(dowrite){
  224. t0 = nsec();
  225. run(wr, cw);
  226. for(i=0; i<multi; i++)
  227. sendp(cw, nil);
  228. t = (nsec() - t0)/1.e9;
  229. print("write: %lld bytes / %.3f seconds = %.6f MB/s\n",
  230. totalbytes, t, (double)totalbytes/1e6/t);
  231. }
  232. if(doread){
  233. t0 = nsec();
  234. run(rd, cr);
  235. for(i=0; i<multi; i++)
  236. sendp(cr, nil);
  237. t = (nsec() - t0)/1.e9;
  238. print("read: %lld bytes / %.3f seconds = %.6f MB/s\n",
  239. totalbytes, t, (double)totalbytes/1e6/t);
  240. }
  241. threadexitsall(nil);
  242. }
  243. /*
  244. * algorithm by
  245. * D. P. Mitchell & J. A. Reeds
  246. */
  247. #define LEN 607
  248. #define TAP 273
  249. #define MASK 0x7fffffffL
  250. #define A 48271
  251. #define M 2147483647
  252. #define Q 44488
  253. #define R 3399
  254. #define NORM (1.0/(1.0+MASK))
  255. static uint32_t rng_vec[LEN];
  256. static uint32_t* rng_tap = rng_vec;
  257. static uint32_t* rng_feed = 0;
  258. static void
  259. isrand(int32_t seed)
  260. {
  261. int32_t lo, hi, x;
  262. int i;
  263. rng_tap = rng_vec;
  264. rng_feed = rng_vec+LEN-TAP;
  265. seed = seed%M;
  266. if(seed < 0)
  267. seed += M;
  268. if(seed == 0)
  269. seed = 89482311;
  270. x = seed;
  271. /*
  272. * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
  273. */
  274. for(i = -20; i < LEN; i++) {
  275. hi = x / Q;
  276. lo = x % Q;
  277. x = A*lo - R*hi;
  278. if(x < 0)
  279. x += M;
  280. if(i >= 0)
  281. rng_vec[i] = x;
  282. }
  283. }
  284. void
  285. xxxsrand(int32_t seed)
  286. {
  287. isrand(seed);
  288. }
  289. int32_t
  290. xxxlrand(void)
  291. {
  292. uint32_t x;
  293. rng_tap--;
  294. if(rng_tap < rng_vec) {
  295. if(rng_feed == 0) {
  296. isrand(1);
  297. rng_tap--;
  298. }
  299. rng_tap += LEN;
  300. }
  301. rng_feed--;
  302. if(rng_feed < rng_vec)
  303. rng_feed += LEN;
  304. x = (*rng_feed + *rng_tap) & MASK;
  305. *rng_feed = x;
  306. return x;
  307. }