bench.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. * Copyright © 2015 Kazunobu Kuriyama <kazunobu.kuriyama@nifty.com>
  3. * Copyright © 2015 Ran Benita <ran234@gmail.com>
  4. * SPDX-License-Identifier: MIT
  5. */
  6. #pragma once
  7. struct bench_time {
  8. long seconds;
  9. long nanoseconds;
  10. };
  11. struct bench {
  12. struct bench_time start;
  13. struct bench_time stop;
  14. };
  15. struct estimate {
  16. long long int elapsed;
  17. long long int stdev;
  18. };
  19. void
  20. bench_start(struct bench *bench);
  21. void
  22. bench_stop(struct bench *bench);
  23. #ifndef _WIN32
  24. void
  25. bench_start2(struct bench *bench);
  26. void
  27. bench_stop2(struct bench *bench);
  28. #else
  29. /* TODO: implement clock_getres for Windows */
  30. #define bench_start2 bench_start
  31. #define bench_stop2 bench_stop
  32. #endif
  33. void
  34. bench_elapsed(const struct bench *bench, struct bench_time *result);
  35. #define bench_time_elapsed_microseconds(elapsed) \
  36. ((elapsed)->nanoseconds / 1000 + 1000000 * (elapsed)->seconds)
  37. #define bench_time_elapsed_nanoseconds(elapsed) \
  38. ((elapsed)->nanoseconds + 1000000000 * (elapsed)->seconds)
  39. /* The caller is responsibile to free() the returned string. */
  40. char *
  41. bench_elapsed_str(const struct bench *bench);
  42. /* Bench method adapted from: https://hackage.haskell.org/package/tasty-bench */
  43. #define BENCH(target_stdev, n, time, est, ...) do { \
  44. struct bench _bench; \
  45. struct bench_time _t1; \
  46. struct bench_time _t2; \
  47. n = 1; \
  48. bench_start2(&_bench); \
  49. do { __VA_ARGS__ } while (0); \
  50. bench_stop2(&_bench); \
  51. bench_elapsed(&_bench, &_t1); \
  52. do { \
  53. bench_start2(&_bench); \
  54. for (unsigned int k = 0; k < 2 * n; k++) { \
  55. __VA_ARGS__ \
  56. } \
  57. bench_stop2(&_bench); \
  58. bench_elapsed(&_bench, &_t2); \
  59. predictPerturbed(&_t1, &_t2, &est); \
  60. if (est.stdev < (long long)(MAX(0, target_stdev * (double)est.elapsed))) {\
  61. scale_estimate(est, n); \
  62. time = _t2; \
  63. n *= 2; \
  64. break; \
  65. } \
  66. n *= 2; \
  67. _t1 = _t2; \
  68. } while (1); \
  69. } while (0)
  70. void
  71. predictPerturbed(const struct bench_time *t1, const struct bench_time *t2,
  72. struct estimate *est);
  73. #define scale_estimate(est, n) do { \
  74. (est).elapsed /= (n); \
  75. (est).stdev /= (n); \
  76. } while (0);