bench-malloc-tcache.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /* Benchmark tcache hotpath allocations.
  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. #ifndef TEST_FUNC
  16. # define TEST_FUNC(size) malloc(size)
  17. # define TEST_NAME "malloc"
  18. #endif
  19. #include <errno.h>
  20. #include <signal.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <sys/time.h>
  25. #include <sys/resource.h>
  26. #include "bench-util.h"
  27. #include "bench-util.c"
  28. #include "bench-timing.h"
  29. #include "json-lib.h"
  30. /* Benchmark duration in seconds. */
  31. #define BENCHMARK_DURATION 3
  32. static volatile bool timeout;
  33. size_t alloc_size;
  34. static void
  35. alarm_handler (int signum)
  36. {
  37. timeout = true;
  38. }
  39. struct bench_result {
  40. size_t iters;
  41. timing_t elapsed;
  42. };
  43. static __always_inline size_t
  44. malloc_benchmark_loop (void **elems, size_t nr_items)
  45. {
  46. size_t iters = nr_items;
  47. while (!timeout)
  48. {
  49. elems[iters % nr_items] = TEST_FUNC (alloc_size);
  50. iters++;
  51. free (elems[iters % nr_items]);
  52. }
  53. return iters - nr_items;
  54. }
  55. static void
  56. do_benchmark (struct bench_result *res)
  57. {
  58. timing_t start, stop;
  59. void *elems[10];
  60. memset (elems, 0, sizeof(elems));
  61. alarm (BENCHMARK_DURATION);
  62. /* Ramp up cpu before measuring. */
  63. bench_start ();
  64. TIMING_NOW (start);
  65. res[0].iters = malloc_benchmark_loop (elems, 1);
  66. TIMING_NOW (stop);
  67. TIMING_DIFF (res[0].elapsed, start, stop);
  68. timeout = false;
  69. alarm (BENCHMARK_DURATION);
  70. bench_start ();
  71. TIMING_NOW (start);
  72. res[1].iters = malloc_benchmark_loop (elems, 4);
  73. TIMING_NOW (stop);
  74. TIMING_DIFF (res[1].elapsed, start, stop);
  75. }
  76. static void usage (const char *name)
  77. {
  78. fprintf (stderr, "%s: <alloc_size>\n", name);
  79. exit (1);
  80. }
  81. int
  82. main (int argc, char **argv)
  83. {
  84. json_ctx_t json_ctx;
  85. double d_total_s, d_total_i;
  86. struct sigaction act;
  87. if (argc == 1)
  88. alloc_size = 1024;
  89. else if (argc == 2)
  90. {
  91. long ret;
  92. errno = 0;
  93. ret = strtol (argv[1], NULL, 10);
  94. if (errno || ret == 0)
  95. usage (argv[0]);
  96. alloc_size = ret;
  97. }
  98. else
  99. usage (argv[0]);
  100. json_init (&json_ctx, 0, stdout);
  101. json_document_begin (&json_ctx);
  102. json_attr_string (&json_ctx, "timing_type", TIMING_TYPE);
  103. json_attr_object_begin (&json_ctx, "functions");
  104. json_attr_object_begin (&json_ctx, TEST_NAME);
  105. memset (&act, 0, sizeof (act));
  106. act.sa_handler = &alarm_handler;
  107. sigaction (SIGALRM, &act, NULL);
  108. struct bench_result res[2];
  109. memset (res, 0, sizeof (struct bench_result) * 2);
  110. do_benchmark (res);
  111. d_total_s = res[0].elapsed;
  112. d_total_i = res[0].iters;
  113. json_attr_object_begin (&json_ctx, "simple");
  114. json_attr_double (&json_ctx, "alloc_size", alloc_size);
  115. json_attr_double (&json_ctx, "duration", d_total_s);
  116. json_attr_double (&json_ctx, "iterations", d_total_i);
  117. json_attr_double (&json_ctx, "time_per_iteration", d_total_s / d_total_i);
  118. json_attr_object_end (&json_ctx);
  119. d_total_s = res[1].elapsed;
  120. d_total_i = res[1].iters;
  121. json_attr_object_begin (&json_ctx, "optimized");
  122. json_attr_double (&json_ctx, "alloc_size", alloc_size);
  123. json_attr_double (&json_ctx, "duration", d_total_s);
  124. json_attr_double (&json_ctx, "iterations", d_total_i);
  125. json_attr_double (&json_ctx, "time_per_iteration", d_total_s / d_total_i);
  126. json_attr_object_end (&json_ctx);
  127. json_attr_object_end (&json_ctx);
  128. json_attr_object_end (&json_ctx);
  129. json_document_end (&json_ctx);
  130. return 0;
  131. }