lib_timing.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. /*
  2. * a timing utilities library
  3. *
  4. * Requires 64bit integers to work.
  5. *
  6. * %W% %@%
  7. *
  8. * Copyright (c) 1994-1998 Larry McVoy.
  9. */
  10. #define _LIB /* bench.h needs this */
  11. #include "bench.h"
  12. #include "confidence.h"
  13. #include <math.h>
  14. //#define _DEBUG
  15. #ifdef KVM_LMBENCH
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <sys/ioctl.h>
  19. #include "../../kvmbenchmark/pvclock_bench.h"
  20. #endif
  21. #define nz(x) ((x) == 0 ? 1 : (x))
  22. /*
  23. * I know you think these should be 2^10 and 2^20, but people are quoting
  24. * disk sizes in powers of 10, and bandwidths are all power of ten.
  25. * Deal with it.
  26. */
  27. #define MB (1000*1000.0)
  28. #define KB (1000.0)
  29. static double u_var, u_mean, ops_s_mean, ops_s_var;
  30. static struct timeval start_tv, stop_tv, stop_mean_tv, stop_var_tv;
  31. FILE *ftiming;
  32. volatile uint64 use_result_dummy; /* !static for optimizers. */
  33. static uint64 iterations;
  34. static void init_timing(void);
  35. #if defined(hpux) || defined(__hpux)
  36. #include <sys/mman.h>
  37. #endif
  38. #ifdef RUSAGE
  39. #include <sys/resource.h>
  40. #define SECS(tv) (tv.tv_sec + tv.tv_usec / 1000000.0)
  41. #define mine(f) (int)(ru_stop.f - ru_start.f)
  42. static struct rusage ru_start, ru_stop;
  43. void
  44. rusage(void)
  45. {
  46. double sys, user, idle;
  47. double per;
  48. sys = SECS(ru_stop.ru_stime) - SECS(ru_start.ru_stime);
  49. user = SECS(ru_stop.ru_utime) - SECS(ru_start.ru_utime);
  50. idle = timespent() - (sys + user);
  51. per = idle / timespent() * 100;
  52. if (!ftiming) ftiming = stderr;
  53. fprintf(ftiming, "real=%.2f sys=%.2f user=%.2f idle=%.2f stall=%.0f%% ",
  54. timespent(), sys, user, idle, per);
  55. fprintf(ftiming, "rd=%d wr=%d min=%d maj=%d ctx=%d\n",
  56. mine(ru_inblock), mine(ru_oublock),
  57. mine(ru_minflt), mine(ru_majflt),
  58. mine(ru_nvcsw) + mine(ru_nivcsw));
  59. }
  60. #endif /* RUSAGE */
  61. /*
  62. * Redirect output someplace else.
  63. */
  64. void
  65. timing(FILE *out)
  66. {
  67. ftiming = out;
  68. }
  69. /*
  70. * Start timing now.
  71. */
  72. void
  73. start(struct timeval *tv)
  74. {
  75. if (tv == NULL) {
  76. tv = &start_tv;
  77. }
  78. #ifdef RUSAGE
  79. getrusage(RUSAGE_SELF, &ru_start);
  80. #endif
  81. (void) gettimeofday(tv, (struct timezone *) 0);
  82. }
  83. /*
  84. * Stop timing and return real time in microseconds.
  85. */
  86. uint64
  87. stop(struct timeval *begin, struct timeval *end)
  88. {
  89. if (end == NULL) {
  90. end = &stop_tv;
  91. }
  92. (void) gettimeofday(end, (struct timezone *) 0);
  93. #ifdef RUSAGE
  94. getrusage(RUSAGE_SELF, &ru_stop);
  95. #endif
  96. if (begin == NULL) {
  97. begin = &start_tv;
  98. }
  99. return tvdelta(begin, end);
  100. }
  101. uint64
  102. now(void)
  103. {
  104. struct timeval t;
  105. uint64 m;
  106. (void) gettimeofday(&t, (struct timezone *) 0);
  107. m = t.tv_sec;
  108. m *= 1000000;
  109. m += t.tv_usec;
  110. return (m);
  111. }
  112. double
  113. Now(void)
  114. {
  115. struct timeval t;
  116. (void) gettimeofday(&t, (struct timezone *) 0);
  117. return (t.tv_sec * 1000000.0 + t.tv_usec);
  118. }
  119. uint64
  120. delta(void)
  121. {
  122. static struct timeval last;
  123. struct timeval t;
  124. struct timeval diff;
  125. uint64 m;
  126. (void) gettimeofday(&t, (struct timezone *) 0);
  127. if (last.tv_usec) {
  128. tvsub(&diff, &t, &last);
  129. last = t;
  130. m = diff.tv_sec;
  131. m *= 1000000;
  132. m += diff.tv_usec;
  133. return (m);
  134. } else {
  135. last = t;
  136. return (0);
  137. }
  138. }
  139. double
  140. Delta(void)
  141. {
  142. struct timeval t;
  143. struct timeval diff;
  144. (void) gettimeofday(&t, (struct timezone *) 0);
  145. tvsub(&diff, &t, &start_tv);
  146. return (diff.tv_sec + diff.tv_usec / 1000000.0);
  147. }
  148. void
  149. save_n(uint64 n)
  150. {
  151. iterations = n;
  152. }
  153. uint64
  154. get_n(void)
  155. {
  156. return (iterations);
  157. }
  158. /*
  159. * Make the time spend be usecs.
  160. */
  161. void
  162. settime(uint64 usecs)
  163. {
  164. bzero((void*)&start_tv, sizeof(start_tv));
  165. stop_tv.tv_sec = usecs / 1000000;
  166. stop_tv.tv_usec = usecs % 1000000;
  167. }
  168. void
  169. setmeantime(double usecs)
  170. {
  171. u_mean = usecs;
  172. }
  173. void
  174. setvariancetime(double usecs)
  175. {
  176. u_var = usecs;
  177. }
  178. void
  179. setmeanratetime(double usecs)
  180. {
  181. ops_s_mean = usecs;
  182. }
  183. void
  184. setvarianceratetime(double usecs)
  185. {
  186. ops_s_var = usecs;
  187. }
  188. void
  189. bandwidth(uint64 bytes, uint64 times, int verbose)
  190. {
  191. struct timeval tdiff;
  192. double mb, secs;
  193. tvsub(&tdiff, &stop_tv, &start_tv);
  194. secs = tdiff.tv_sec;
  195. secs *= 1000000;
  196. secs += tdiff.tv_usec;
  197. secs /= 1000000;
  198. secs /= times;
  199. mb = bytes / MB;
  200. if (!ftiming) ftiming = stderr;
  201. if (verbose) {
  202. (void) fprintf(ftiming,
  203. "%.4f MB in %.4f secs, %.4f MB/sec\n",
  204. mb, secs, mb/secs);
  205. } else {
  206. if (mb < 1) {
  207. (void) fprintf(ftiming, "%.6f ", mb);
  208. } else {
  209. (void) fprintf(ftiming, "%.2f ", mb);
  210. }
  211. if (mb / secs < 1) {
  212. (void) fprintf(ftiming, "%.6f\n", mb/secs);
  213. } else {
  214. (void) fprintf(ftiming, "%.2f\n", mb/secs);
  215. }
  216. }
  217. }
  218. void
  219. kb(uint64 bytes)
  220. {
  221. struct timeval td;
  222. double s, bs;
  223. tvsub(&td, &stop_tv, &start_tv);
  224. s = td.tv_sec + td.tv_usec / 1000000.0;
  225. bs = bytes / nz(s);
  226. if (!ftiming) ftiming = stderr;
  227. (void) fprintf(ftiming, "%.0f KB/sec\n", bs / KB);
  228. }
  229. void
  230. mb(uint64 bytes)
  231. {
  232. struct timeval td;
  233. double s, bs;
  234. tvsub(&td, &stop_tv, &start_tv);
  235. s = td.tv_sec + td.tv_usec / 1000000.0;
  236. bs = bytes / nz(s);
  237. if (!ftiming) ftiming = stderr;
  238. (void) fprintf(ftiming, "%.2f MB/sec\n", bs / MB);
  239. }
  240. void
  241. latency(uint64 xfers, uint64 size)
  242. {
  243. struct timeval td;
  244. double s;
  245. if (!ftiming) ftiming = stderr;
  246. tvsub(&td, &stop_tv, &start_tv);
  247. s = td.tv_sec + td.tv_usec / 1000000.0;
  248. if (xfers > 1) {
  249. fprintf(ftiming, "%d %dKB xfers in %.2f secs, ",
  250. (int) xfers, (int) (size / KB), s);
  251. } else {
  252. fprintf(ftiming, "%.1fKB in ", size / KB);
  253. }
  254. if ((s * 1000 / xfers) > 100) {
  255. fprintf(ftiming, "%.0f millisec%s, ",
  256. s * 1000 / xfers, xfers > 1 ? "/xfer" : "s");
  257. } else {
  258. fprintf(ftiming, "%.4f millisec%s, ",
  259. s * 1000 / xfers, xfers > 1 ? "/xfer" : "s");
  260. }
  261. if (((xfers * size) / (MB * s)) > 1) {
  262. fprintf(ftiming, "%.2f MB/sec\n", (xfers * size) / (MB * s));
  263. } else {
  264. fprintf(ftiming, "%.2f KB/sec\n", (xfers * size) / (KB * s));
  265. }
  266. }
  267. void
  268. context(uint64 xfers)
  269. {
  270. struct timeval td;
  271. double s;
  272. tvsub(&td, &stop_tv, &start_tv);
  273. s = td.tv_sec + td.tv_usec / 1000000.0;
  274. if (!ftiming) ftiming = stderr;
  275. fprintf(ftiming,
  276. "%d context switches in %.2f secs, %.0f microsec/switch\n",
  277. (int)xfers, s, s * 1000000 / xfers);
  278. }
  279. void
  280. nano(char *s, uint64 n)
  281. {
  282. struct timeval td;
  283. double micro;
  284. tvsub(&td, &stop_tv, &start_tv);
  285. micro = td.tv_sec * 1000000 + td.tv_usec;
  286. micro *= 1000;
  287. if (!ftiming) ftiming = stderr;
  288. fprintf(ftiming, "%s: %.0f nanoseconds\n", s, micro / n);
  289. }
  290. /*
  291. uint64
  292. getmeantime(void)
  293. {
  294. return (tvdelta(&start_tv, &stop_mean_tv));
  295. }
  296. uint64
  297. getvariancetime(void)
  298. {
  299. return (tvdelta(&start_tv, &stop_var_tv));
  300. }
  301. */
  302. static result_t results;
  303. void
  304. micro(char *s, uint64 n)
  305. {
  306. struct timeval td;
  307. double micro, mean, var;
  308. tvsub(&td, &stop_tv, &start_tv);
  309. micro = td.tv_sec * 1000000 + td.tv_usec;
  310. micro /= n;
  311. if (micro == 0.0) return;
  312. mean = getmeantime();
  313. var = getvariancetime();
  314. if (var < 0.0)
  315. var = 0.0;
  316. if (!ftiming) ftiming = stderr;
  317. fprintf(ftiming, "%s median=%.4lf [mean=%.4lf +/-%.4lf] microseconds\n",
  318. s, micro, mean, ci_width(sqrt(var), results.N));
  319. fprintf(ftiming, "var: %lf sd: %lf runs: %d\n",
  320. var, sqrt(var), results.N);
  321. }
  322. void
  323. micromb(uint64 sz, uint64 n)
  324. {
  325. struct timeval td;
  326. double mb, micro;
  327. tvsub(&td, &stop_tv, &start_tv);
  328. micro = td.tv_sec * 1000000 + td.tv_usec;
  329. micro /= n;
  330. mb = sz;
  331. mb /= MB;
  332. if (!ftiming) ftiming = stderr;
  333. if (micro >= 10) {
  334. fprintf(ftiming, "%.6f %.0f\n", mb, micro);
  335. } else {
  336. fprintf(ftiming, "%.6f %.3f\n", mb, micro);
  337. }
  338. }
  339. void
  340. milli(char *s, uint64 n)
  341. {
  342. struct timeval td;
  343. uint64 milli;
  344. tvsub(&td, &stop_tv, &start_tv);
  345. milli = td.tv_sec * 1000 + td.tv_usec / 1000;
  346. milli /= n;
  347. if (!ftiming) ftiming = stderr;
  348. fprintf(ftiming, "%s: %d milliseconds\n", s, (int)milli);
  349. }
  350. void
  351. ptime(uint64 n)
  352. {
  353. struct timeval td;
  354. double s;
  355. tvsub(&td, &stop_tv, &start_tv);
  356. s = td.tv_sec + td.tv_usec / 1000000.0;
  357. if (!ftiming) ftiming = stderr;
  358. fprintf(ftiming,
  359. "%d in %.2f secs, %.0f microseconds each\n",
  360. (int)n, s, s * 1000000 / n);
  361. }
  362. uint64
  363. tvdelta(struct timeval *start, struct timeval *stop)
  364. {
  365. struct timeval td;
  366. uint64 usecs;
  367. tvsub(&td, stop, start);
  368. usecs = td.tv_sec;
  369. usecs *= 1000000;
  370. usecs += td.tv_usec;
  371. return (usecs);
  372. }
  373. void
  374. tvsub(struct timeval * tdiff, struct timeval * t1, struct timeval * t0)
  375. {
  376. tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  377. tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  378. if (tdiff->tv_usec < 0 && tdiff->tv_sec > 0) {
  379. tdiff->tv_sec--;
  380. tdiff->tv_usec += 1000000;
  381. assert(tdiff->tv_usec >= 0);
  382. }
  383. /* time shouldn't go backwards!!! */
  384. if (tdiff->tv_usec < 0 || t1->tv_sec < t0->tv_sec) {
  385. tdiff->tv_sec = 0;
  386. tdiff->tv_usec = 0;
  387. }
  388. }
  389. double getmeantime(void)
  390. {
  391. return u_mean;
  392. }
  393. double getvariancetime(void)
  394. {
  395. return u_var;
  396. }
  397. double getmeanratetime(void)
  398. {
  399. return ops_s_mean;
  400. }
  401. double getvarianceratetime(void)
  402. {
  403. return ops_s_var;
  404. }
  405. /**
  406. * returns time in microseconds
  407. */
  408. uint64
  409. gettime(void)
  410. {
  411. return (tvdelta(&start_tv, &stop_tv));
  412. }
  413. double
  414. timespent(void)
  415. {
  416. struct timeval td;
  417. tvsub(&td, &stop_tv, &start_tv);
  418. return (td.tv_sec + td.tv_usec / 1000000.0);
  419. }
  420. static char p64buf[10][20];
  421. static int n;
  422. char *
  423. p64(uint64 big)
  424. {
  425. char *s = p64buf[n++];
  426. if (n == 10) n = 0;
  427. #ifdef linux
  428. {
  429. int *a = (int*)&big;
  430. if (a[1]) {
  431. sprintf(s, "0x%x%08x", a[1], a[0]);
  432. } else {
  433. sprintf(s, "0x%x", a[0]);
  434. }
  435. }
  436. #endif
  437. #ifdef __sgi
  438. sprintf(s, "0x%llx", big);
  439. #endif
  440. return (s);
  441. }
  442. char *
  443. p64sz(uint64 big)
  444. {
  445. double d = big;
  446. char *tags = " KMGTPE";
  447. int t = 0;
  448. char *s = p64buf[n++];
  449. if (n == 10) n = 0;
  450. while (d > 512) t++, d /= 1024;
  451. if (d == 0) {
  452. return ("0");
  453. }
  454. if (d < 100) {
  455. sprintf(s, "%.4f%c", d, tags[t]);
  456. } else {
  457. sprintf(s, "%.2f%c", d, tags[t]);
  458. }
  459. return (s);
  460. }
  461. char
  462. last(char *s)
  463. {
  464. while (*s++)
  465. ;
  466. return (s[-2]);
  467. }
  468. size_t
  469. bytes(char *s)
  470. {
  471. uint64 n;
  472. sscanf(s, "%llu", &n);
  473. if ((last(s) == 'k') || (last(s) == 'K'))
  474. n *= 1024;
  475. if ((last(s) == 'm') || (last(s) == 'M'))
  476. n *= (1024 * 1024);
  477. return ((size_t)n);
  478. }
  479. void
  480. use_int(int result) { use_result_dummy += result; }
  481. void
  482. use_pointer(void *result) { use_result_dummy += *(int *)result; }
  483. void
  484. insertinit(result_t *r)
  485. {
  486. int i;
  487. r->N = 0;
  488. for (i = 0; i < TRIES; i++) {
  489. r->u[i] = 0;
  490. r->n[i] = 1;
  491. }
  492. }
  493. /* biggest to smallest */
  494. void
  495. insertsort(uint64 u, uint64 n, result_t *r)
  496. {
  497. int i, j;
  498. if (u == 0) return;
  499. for (i = 0; i < r->N; ++i) {
  500. if (u/(double)n > r->u[i]/(double)r->n[i]) {
  501. for (j = r->N; j > i; --j) {
  502. r->u[j] = r->u[j-1];
  503. r->n[j] = r->n[j-1];
  504. }
  505. break;
  506. }
  507. }
  508. r->u[i] = u;
  509. r->n[i] = n;
  510. r->N++;
  511. }
  512. //static result_t results;
  513. void
  514. print_results(int details)
  515. {
  516. int i;
  517. for (i = 0; i < results.N; ++i) {
  518. fprintf(stderr, "%.2f", (double)results.u[i]/results.n[i]);
  519. if (i < results.N - 1) fprintf(stderr, " ");
  520. }
  521. fprintf(stderr, "\n");
  522. if (details) {
  523. for (i = 0; i < results.N; ++i) {
  524. fprintf(stderr,
  525. "%llu/%llu", results.u[i], results.n[i]);
  526. if (i < results.N - 1) fprintf(stderr, " ");
  527. }
  528. fprintf(stderr, "\n");
  529. }
  530. }
  531. void
  532. get_results(result_t *r)
  533. {
  534. *r = results;
  535. }
  536. /*
  537. void
  538. setmeantime(uint64 usecs)
  539. {
  540. bzero((void*)&start_tv, sizeof(start_tv));
  541. stop_mean_tv.tv_sec = usecs / 1000000;
  542. stop_mean_tv.tv_usec = usecs % 1000000;
  543. }
  544. void
  545. setvariancetime(uint64 usecs)
  546. {
  547. bzero((void*)&start_tv, sizeof(start_tv));
  548. stop_var_tv.tv_sec = usecs / 1000000;
  549. stop_var_tv.tv_usec = usecs % 1000000;
  550. }
  551. */
  552. void
  553. save_results(result_t *r)
  554. {
  555. results = *r;
  556. save_median();
  557. save_mean();
  558. save_variance();
  559. }
  560. void
  561. save_minimum()
  562. {
  563. if (results.N == 0) {
  564. save_n(1);
  565. settime(0);
  566. } else {
  567. save_n(results.n[results.N - 1]);
  568. settime(results.u[results.N - 1]);
  569. }
  570. }
  571. void
  572. save_median()
  573. {
  574. int i = results.N / 2;
  575. uint64 u, n;
  576. if (results.N == 0) {
  577. n = 1;
  578. u = 0;
  579. } else if (results.N % 2) {
  580. n = results.n[i];
  581. u = results.u[i];
  582. } else {
  583. n = (results.n[i] + results.n[i-1]) / 2;
  584. u = (results.u[i] + results.u[i-1]) / 2;
  585. }
  586. save_n(n); settime(u);
  587. }
  588. void
  589. save_mean()
  590. {
  591. int i;
  592. double sum = 0;
  593. double sum_r = 0;
  594. double mean, mean_ops_s;
  595. if (results.N == 0) {
  596. mean = 0.;
  597. mean_ops_s = 0.;
  598. } else {
  599. for(i = 0; i < results.N; i++)
  600. sum += (double)results.u[i] / (double)results.n[i];
  601. mean = sum / (double)results.N;
  602. /* harmonic average for rates = n / (sum^n_{i=1} 1/rate_i) */
  603. mean_ops_s = ((double)results.N * 1000000.) / sum;
  604. }
  605. setmeantime(mean);
  606. setmeanratetime(mean_ops_s);
  607. }
  608. double calc_variance(double mean, double *times, int size)
  609. {
  610. unsigned int i;
  611. double sum;
  612. if (size <= 1)
  613. return 0;
  614. for (i = 0, sum = 0; i < size; i++)
  615. sum += (times[i] - mean) * (times[i] - mean);
  616. return sum / (double) (size - 1);
  617. }
  618. double calc_variance_rate(double mean, double *times, int size,
  619. int ops_per_measure)
  620. {
  621. unsigned int i;
  622. double sum, x_r;
  623. if (size <= 1)
  624. return 0;
  625. for (i = 0, sum = 0; i < size; i++) {
  626. x_r = (double) ops_per_measure / (double) times[i];
  627. sum += (x_r - mean) * (x_r - mean);
  628. }
  629. return sum / (double) (size - 1);
  630. }
  631. double calc_mean(double *times, int size)
  632. {
  633. unsigned int i;
  634. double sum;
  635. if (size <= 0)
  636. return 0;
  637. for (i = 0, sum = 0; i < size; i++)
  638. sum += times[i];
  639. return sum / (double) size;
  640. }
  641. double calc_mean_rate(double *times, int size, int ops_per_measure)
  642. {
  643. int i;
  644. double sum;
  645. for(i = 0, sum = 0; i < size; i++)
  646. sum += times[i] / (double) ops_per_measure;
  647. /* harmonic average for rates = n / (sum^n_{i=1} 1/rate_i) */
  648. return ((double)size) / sum;
  649. }
  650. void
  651. save_variance()
  652. {
  653. double mean, variance, sum;
  654. double mean_r, variance_r, sum_r;
  655. int i;
  656. if (results.N == 0) {
  657. sum = 0;
  658. mean = 0;
  659. variance = 0;
  660. sum_r = 0;
  661. mean_r = 0;
  662. variance_r = 0;
  663. goto done;
  664. } else {
  665. mean = getmeantime();
  666. mean_r = getmeanratetime();
  667. if (mean <= 0) {
  668. save_mean();
  669. mean = getmeantime();
  670. mean_r = getmeanratetime();
  671. if (mean <= 0) {
  672. variance = 0;
  673. variance_r = 0;
  674. goto done;
  675. }
  676. }
  677. for (i = 0, sum = 0; i < results.N; i++) {
  678. double x, x_r;
  679. x = (double)results.u[i] / (double)results.n[i];
  680. sum += (x-mean) * (x-mean);
  681. /* multiply by 1000000?: dividing by us, but want ops/s */
  682. x_r = ((double)results.n[i] * 1000000.) / (double)results.u[i];
  683. sum_r += (x_r-mean_r) * (x_r-mean_r);
  684. }
  685. if (results.N == 1) {
  686. variance = sum;
  687. variance_r = sum;
  688. } else {
  689. variance = sum / (double) (results.N - 1);
  690. variance_r = sum_r / (double) (results.N - 1);
  691. }
  692. }
  693. done:
  694. setvariancetime(variance);
  695. setvarianceratetime(variance_r);
  696. }
  697. /*
  698. * The inner loop tracks bench.h but uses a different results array.
  699. */
  700. static long *
  701. one_op(register long *p)
  702. {
  703. BENCH_INNER(p = (long *)*p, 0);
  704. return (p);
  705. }
  706. static long *
  707. two_op(register long *p, register long *q)
  708. {
  709. BENCH_INNER(p = (long *)*q; q = (long*)*p, 0);
  710. return (p);
  711. }
  712. static long *p = (long *)&p;
  713. static long *q = (long *)&q;
  714. double
  715. l_overhead(void)
  716. {
  717. int i;
  718. uint64 N_save, u_save;
  719. static double overhead;
  720. static int initialized = 0;
  721. result_t one, two, r_save;
  722. init_timing();
  723. if (initialized) return (overhead);
  724. initialized = 1;
  725. if (getenv("LOOP_O")) {
  726. overhead = atof(getenv("LOOP_O"));
  727. } else {
  728. get_results(&r_save); N_save = get_n(); u_save = gettime();
  729. insertinit(&one);
  730. insertinit(&two);
  731. for (i = 0; i < TRIES; ++i) {
  732. use_pointer((void*)one_op(p));
  733. if (gettime() > t_overhead())
  734. insertsort(gettime() - t_overhead(), get_n(), &one);
  735. use_pointer((void *)two_op(p, q));
  736. if (gettime() > t_overhead())
  737. insertsort(gettime() - t_overhead(), get_n(), &two);
  738. }
  739. /*
  740. * u1 = (n1 * (overhead + work))
  741. * u2 = (n2 * (overhead + 2 * work))
  742. * ==> overhead = 2. * u1 / n1 - u2 / n2
  743. */
  744. save_results(&one); save_minimum();
  745. overhead = 2. * gettime() / (double)get_n();
  746. save_results(&two); save_minimum();
  747. overhead -= gettime() / (double)get_n();
  748. if (overhead < 0.) overhead = 0.; /* Gag */
  749. save_results(&r_save); save_n(N_save); settime(u_save);
  750. }
  751. return (overhead);
  752. }
  753. /*
  754. * Figure out the timing overhead. This has to track bench.h
  755. */
  756. uint64
  757. t_overhead(void)
  758. {
  759. uint64 N_save, u_save;
  760. static int initialized = 0;
  761. static uint64 overhead = 0;
  762. struct timeval tv;
  763. result_t r_save;
  764. init_timing();
  765. if (initialized) return (overhead);
  766. initialized = 1;
  767. if (getenv("TIMING_O")) {
  768. overhead = atof(getenv("TIMING_O"));
  769. } else if (get_enough(0) <= 50000) {
  770. /* it is not in the noise, so compute it */
  771. int i;
  772. result_t r;
  773. get_results(&r_save); N_save = get_n(); u_save = gettime();
  774. insertinit(&r);
  775. for (i = 0; i < TRIES; ++i) {
  776. BENCH_INNER(gettimeofday(&tv, 0), 0);
  777. insertsort(gettime(), get_n(), &r);
  778. }
  779. save_results(&r);
  780. save_minimum();
  781. overhead = gettime() / get_n();
  782. save_results(&r_save); save_n(N_save); settime(u_save);
  783. }
  784. return (overhead);
  785. }
  786. /*
  787. * Figure out how long to run it.
  788. * If enough == 0, then they want us to figure it out.
  789. * If enough is !0 then return it unless we think it is too short.
  790. */
  791. static int long_enough;
  792. static int compute_enough();
  793. int
  794. get_enough(int e)
  795. {
  796. init_timing();
  797. return (long_enough > e ? long_enough : e);
  798. }
  799. static void
  800. init_timing(void)
  801. {
  802. static int done = 0;
  803. if (done) return;
  804. done = 1;
  805. long_enough = compute_enough();
  806. t_overhead();
  807. l_overhead();
  808. }
  809. typedef long TYPE;
  810. static TYPE **
  811. enough_duration(register long N, register TYPE ** p)
  812. {
  813. #define ENOUGH_DURATION_TEN(one) one one one one one one one one one one
  814. while (N-- > 0) {
  815. ENOUGH_DURATION_TEN(p = (TYPE **) *p;);
  816. }
  817. return (p);
  818. }
  819. static uint64
  820. duration(long N)
  821. {
  822. uint64 usecs;
  823. TYPE *x = (TYPE *)&x;
  824. TYPE **p = (TYPE **)&x;
  825. start(0);
  826. p = enough_duration(N, p);
  827. usecs = stop(0, 0);
  828. use_pointer((void *)p);
  829. return (usecs);
  830. }
  831. /*
  832. * find the minimum time that work "N" takes in "tries" tests
  833. */
  834. static uint64
  835. time_N(long N)
  836. {
  837. int i;
  838. uint64 usecs;
  839. result_t r;
  840. insertinit(&r);
  841. for (i = 1; i < TRIES; ++i) {
  842. usecs = duration(N);
  843. insertsort(usecs, N, &r);
  844. }
  845. save_results(&r);
  846. save_minimum();
  847. return (gettime());
  848. }
  849. /*
  850. * return the amount of work needed to run "enough" microseconds
  851. */
  852. static long
  853. find_N(int enough)
  854. {
  855. int tries;
  856. static long N = 10000;
  857. static uint64 usecs = 0;
  858. if (!usecs) usecs = time_N(N);
  859. for (tries = 0; tries < 10; ++tries) {
  860. if (0.98 * enough < usecs && usecs < 1.02 * enough)
  861. return (N);
  862. if (usecs < 1000)
  863. N *= 10;
  864. else {
  865. double n = N;
  866. n /= usecs;
  867. n *= enough;
  868. N = n + 1;
  869. }
  870. usecs = time_N(N);
  871. }
  872. return (0);
  873. }
  874. /*
  875. * We want to verify that small modifications proportionally affect the runtime
  876. */
  877. static double test_points[] = {1.015, 1.02, 1.035};
  878. static int
  879. test_time(int enough)
  880. {
  881. int i;
  882. long N;
  883. uint64 usecs, expected, baseline, diff;
  884. if ((N = find_N(enough)) <= 0)
  885. return (0);
  886. baseline = time_N(N);
  887. for (i = 0; i < sizeof(test_points) / sizeof(double); ++i) {
  888. usecs = time_N((int)((double) N * test_points[i]));
  889. expected = (uint64)((double)baseline * test_points[i]);
  890. diff = expected > usecs ? expected - usecs : usecs - expected;
  891. if (diff / (double)expected > 0.0025)
  892. return (0);
  893. }
  894. return (1);
  895. }
  896. /*
  897. * We want to find the smallest timing interval that has accurate timing
  898. */
  899. static int possibilities[] = { 5000, 10000, 50000, 100000 };
  900. static int
  901. compute_enough()
  902. {
  903. int i;
  904. if (getenv("ENOUGH")) {
  905. return (atoi(getenv("ENOUGH")));
  906. }
  907. for (i = 0; i < sizeof(possibilities) / sizeof(int); ++i) {
  908. if (test_time(possibilities[i]))
  909. return (possibilities[i]);
  910. }
  911. /*
  912. * if we can't find a timing interval that is sufficient,
  913. * then use SHORT as a default.
  914. */
  915. return (SHORT);
  916. }
  917. /*
  918. * This stuff isn't really lib_timing, but ...
  919. */
  920. void
  921. morefds(void)
  922. {
  923. #ifdef RLIMIT_NOFILE
  924. struct rlimit r;
  925. getrlimit(RLIMIT_NOFILE, &r);
  926. r.rlim_cur = r.rlim_max;
  927. setrlimit(RLIMIT_NOFILE, &r);
  928. #endif
  929. }
  930. void
  931. touch(char *buf, size_t nbytes)
  932. {
  933. static size_t psize;
  934. if (!psize) {
  935. psize = getpagesize();
  936. }
  937. while (nbytes > psize - 1) {
  938. *buf = 1;
  939. buf += psize;
  940. nbytes -= psize;
  941. }
  942. }
  943. #if defined(hpux) || defined(__hpux)
  944. int
  945. getpagesize()
  946. {
  947. return (sysconf(_SC_PAGE_SIZE));
  948. }
  949. #endif
  950. #ifdef WIN32
  951. int
  952. getpagesize()
  953. {
  954. SYSTEM_INFO s;
  955. GetSystemInfo(&s);
  956. return ((int)s.dwPageSize);
  957. }
  958. LARGE_INTEGER
  959. getFILETIMEoffset()
  960. {
  961. SYSTEMTIME s;
  962. FILETIME f;
  963. LARGE_INTEGER t;
  964. s.wYear = 1970;
  965. s.wMonth = 1;
  966. s.wDay = 1;
  967. s.wHour = 0;
  968. s.wMinute = 0;
  969. s.wSecond = 0;
  970. s.wMilliseconds = 0;
  971. SystemTimeToFileTime(&s, &f);
  972. t.QuadPart = f.dwHighDateTime;
  973. t.QuadPart <<= 32;
  974. t.QuadPart |= f.dwLowDateTime;
  975. return (t);
  976. }
  977. int
  978. gettimeofday(struct timeval *tv, struct timezone *tz)
  979. {
  980. LARGE_INTEGER t;
  981. FILETIME f;
  982. double microseconds;
  983. static LARGE_INTEGER offset;
  984. static double frequencyToMicroseconds;
  985. static int initialized = 0;
  986. static BOOL usePerformanceCounter = 0;
  987. if (!initialized) {
  988. LARGE_INTEGER performanceFrequency;
  989. initialized = 1;
  990. usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
  991. if (usePerformanceCounter) {
  992. QueryPerformanceCounter(&offset);
  993. frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
  994. } else {
  995. offset = getFILETIMEoffset();
  996. frequencyToMicroseconds = 10.;
  997. }
  998. }
  999. if (usePerformanceCounter) QueryPerformanceCounter(&t);
  1000. else {
  1001. GetSystemTimeAsFileTime(&f);
  1002. t.QuadPart = f.dwHighDateTime;
  1003. t.QuadPart <<= 32;
  1004. t.QuadPart |= f.dwLowDateTime;
  1005. }
  1006. t.QuadPart -= offset.QuadPart;
  1007. microseconds = (double)t.QuadPart / frequencyToMicroseconds;
  1008. t.QuadPart = microseconds;
  1009. tv->tv_sec = t.QuadPart / 1000000;
  1010. tv->tv_usec = t.QuadPart % 1000000;
  1011. return (0);
  1012. }
  1013. #endif
  1014. #ifdef KVM_LMBENCH
  1015. static int fd_pvclock_bench = -1;
  1016. int getbenchtimeofday(struct timeval *tv)
  1017. {
  1018. //pvclock_bm_get tv;
  1019. int ret = 0;
  1020. if (fd_pvclock_bench < 0) {
  1021. fd_pvclock_bench = open("/proc/pvclock/pvclock_bm_entry", O_RDONLY);
  1022. if (fd_pvclock_bench < 0)
  1023. {
  1024. printf("Open error: \n");
  1025. ret = -1;
  1026. goto END;
  1027. }
  1028. }
  1029. if(ioctl(fd_pvclock_bench, PVCLOCK_BM_GET, (unsigned long)tv) < 0)
  1030. {
  1031. printf ("IOCTL PVBLOCK_BM_GET error:\n");
  1032. ret = -1;
  1033. goto END;
  1034. }
  1035. //printf("pvclock bench succeeds: tv = {%ld, %ld}\n\n", tv->tv_sec, tv->tv_usec);
  1036. END:
  1037. return ret;
  1038. }
  1039. #endif
  1040. void
  1041. TRACE(char* format, ...)
  1042. {
  1043. va_list ap;
  1044. va_start(ap, format);
  1045. #ifdef _DEBUG
  1046. vfprintf(stderr, format, ap);
  1047. fflush(stderr);
  1048. #endif
  1049. va_end(ap);
  1050. }