bench-skeleton.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* Skeleton for benchmark programs.
  2. Copyright (C) 2013-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <string.h>
  16. #include <stdint.h>
  17. #include <stdbool.h>
  18. #include <stdio.h>
  19. #include <time.h>
  20. #include <inttypes.h>
  21. #include "bench-timing.h"
  22. #include "json-lib.h"
  23. #include "bench-util.h"
  24. #include "bench-util.c"
  25. #define TIMESPEC_AFTER(a, b) \
  26. (((a).tv_sec == (b).tv_sec) \
  27. ? ((a).tv_nsec > (b).tv_nsec) \
  28. : ((a).tv_sec > (b).tv_sec))
  29. int
  30. main (int argc, char **argv)
  31. {
  32. unsigned long i, k;
  33. struct timespec runtime;
  34. timing_t start, end;
  35. bool detailed = false;
  36. json_ctx_t json_ctx;
  37. if (argc == 2 && !strcmp (argv[1], "-d"))
  38. detailed = true;
  39. bench_start ();
  40. memset (&runtime, 0, sizeof (runtime));
  41. unsigned long iters = 2000;
  42. #ifdef BENCH_INIT
  43. BENCH_INIT ();
  44. #endif
  45. json_init (&json_ctx, 2, stdout);
  46. /* Begin function. */
  47. json_attr_object_begin (&json_ctx, FUNCNAME);
  48. for (int v = 0; v < NUM_VARIANTS; v++)
  49. {
  50. /* Run for approximately DURATION seconds. */
  51. clock_gettime (CLOCK_MONOTONIC_RAW, &runtime);
  52. runtime.tv_sec += DURATION;
  53. bool is_bench = strncmp (VARIANT (v), "workload-", 9) == 0;
  54. double d_total_i = 0;
  55. timing_t total = 0, max = 0, min = 0x7fffffffffffffff;
  56. timing_t throughput = 0, latency = 0;
  57. int64_t c = 0;
  58. uint64_t cur;
  59. BENCH_VARS;
  60. while (1)
  61. {
  62. if (is_bench)
  63. {
  64. /* Benchmark a real trace of calls - all samples are iterated
  65. over once before repeating. This models actual use more
  66. accurately than repeating the same sample many times. */
  67. TIMING_NOW (start);
  68. for (k = 0; k < iters; k++)
  69. for (i = 0; i < NUM_SAMPLES (v); i++)
  70. BENCH_FUNC (v, i);
  71. TIMING_NOW (end);
  72. TIMING_DIFF (cur, start, end);
  73. TIMING_ACCUM (throughput, cur);
  74. TIMING_NOW (start);
  75. for (k = 0; k < iters; k++)
  76. for (i = 0; i < NUM_SAMPLES (v); i++)
  77. BENCH_FUNC_LAT (v, i);
  78. TIMING_NOW (end);
  79. TIMING_DIFF (cur, start, end);
  80. TIMING_ACCUM (latency, cur);
  81. d_total_i += iters * NUM_SAMPLES (v);
  82. }
  83. else
  84. for (i = 0; i < NUM_SAMPLES (v); i++)
  85. {
  86. TIMING_NOW (start);
  87. for (k = 0; k < iters; k++)
  88. BENCH_FUNC (v, i);
  89. TIMING_NOW (end);
  90. TIMING_DIFF (cur, start, end);
  91. if (cur > max)
  92. max = cur;
  93. if (cur < min)
  94. min = cur;
  95. TIMING_ACCUM (total, cur);
  96. /* Accumulate timings for the value. In the end we will divide
  97. by the total iterations. */
  98. RESULT_ACCUM (cur, v, i, c * iters, (c + 1) * iters);
  99. d_total_i += iters;
  100. }
  101. c++;
  102. struct timespec curtime;
  103. memset (&curtime, 0, sizeof (curtime));
  104. clock_gettime (CLOCK_MONOTONIC_RAW, &curtime);
  105. if (TIMESPEC_AFTER (curtime, runtime))
  106. goto done;
  107. }
  108. double d_total_s;
  109. double d_iters;
  110. done:
  111. d_total_s = total;
  112. d_iters = iters;
  113. /* Begin variant. */
  114. json_attr_object_begin (&json_ctx, VARIANT (v));
  115. if (is_bench)
  116. {
  117. json_attr_double (&json_ctx, "duration", throughput + latency);
  118. json_attr_double (&json_ctx, "iterations", 2 * d_total_i);
  119. json_attr_double (&json_ctx, "reciprocal-throughput",
  120. throughput / d_total_i);
  121. json_attr_double (&json_ctx, "latency", latency / d_total_i);
  122. json_attr_double (&json_ctx, "max-throughput",
  123. d_total_i / throughput * 1000000000.0);
  124. json_attr_double (&json_ctx, "min-throughput",
  125. d_total_i / latency * 1000000000.0);
  126. }
  127. else
  128. {
  129. json_attr_double (&json_ctx, "duration", d_total_s);
  130. json_attr_double (&json_ctx, "iterations", d_total_i);
  131. json_attr_double (&json_ctx, "max", max / d_iters);
  132. json_attr_double (&json_ctx, "min", min / d_iters);
  133. json_attr_double (&json_ctx, "mean", d_total_s / d_total_i);
  134. }
  135. if (detailed && !is_bench)
  136. {
  137. json_array_begin (&json_ctx, "timings");
  138. for (int i = 0; i < NUM_SAMPLES (v); i++)
  139. json_element_double (&json_ctx, RESULT (v, i));
  140. json_array_end (&json_ctx);
  141. }
  142. /* End variant. */
  143. json_attr_object_end (&json_ctx);
  144. }
  145. /* End function. */
  146. json_attr_object_end (&json_ctx);
  147. return 0;
  148. }