benchmark.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * benchmark.c:
  4. * Author: Konstantin Khlebnikov <[email protected]>
  5. */
  6. #include <linux/radix-tree.h>
  7. #include <linux/slab.h>
  8. #include <linux/errno.h>
  9. #include <time.h>
  10. #include "test.h"
  11. #define NSEC_PER_SEC 1000000000L
  12. static long long benchmark_iter(struct radix_tree_root *root, bool tagged)
  13. {
  14. volatile unsigned long sink = 0;
  15. struct radix_tree_iter iter;
  16. struct timespec start, finish;
  17. long long nsec;
  18. int l, loops = 1;
  19. void **slot;
  20. #ifdef BENCHMARK
  21. again:
  22. #endif
  23. clock_gettime(CLOCK_MONOTONIC, &start);
  24. for (l = 0; l < loops; l++) {
  25. if (tagged) {
  26. radix_tree_for_each_tagged(slot, root, &iter, 0, 0)
  27. sink ^= (unsigned long)slot;
  28. } else {
  29. radix_tree_for_each_slot(slot, root, &iter, 0)
  30. sink ^= (unsigned long)slot;
  31. }
  32. }
  33. clock_gettime(CLOCK_MONOTONIC, &finish);
  34. nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
  35. (finish.tv_nsec - start.tv_nsec);
  36. #ifdef BENCHMARK
  37. if (loops == 1 && nsec * 5 < NSEC_PER_SEC) {
  38. loops = NSEC_PER_SEC / nsec / 4 + 1;
  39. goto again;
  40. }
  41. #endif
  42. nsec /= loops;
  43. return nsec;
  44. }
  45. static void benchmark_insert(struct radix_tree_root *root,
  46. unsigned long size, unsigned long step)
  47. {
  48. struct timespec start, finish;
  49. unsigned long index;
  50. long long nsec;
  51. clock_gettime(CLOCK_MONOTONIC, &start);
  52. for (index = 0 ; index < size ; index += step)
  53. item_insert(root, index);
  54. clock_gettime(CLOCK_MONOTONIC, &finish);
  55. nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
  56. (finish.tv_nsec - start.tv_nsec);
  57. printv(2, "Size: %8ld, step: %8ld, insertion: %15lld ns\n",
  58. size, step, nsec);
  59. }
  60. static void benchmark_tagging(struct radix_tree_root *root,
  61. unsigned long size, unsigned long step)
  62. {
  63. struct timespec start, finish;
  64. unsigned long index;
  65. long long nsec;
  66. clock_gettime(CLOCK_MONOTONIC, &start);
  67. for (index = 0 ; index < size ; index += step)
  68. radix_tree_tag_set(root, index, 0);
  69. clock_gettime(CLOCK_MONOTONIC, &finish);
  70. nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
  71. (finish.tv_nsec - start.tv_nsec);
  72. printv(2, "Size: %8ld, step: %8ld, tagging: %17lld ns\n",
  73. size, step, nsec);
  74. }
  75. static void benchmark_delete(struct radix_tree_root *root,
  76. unsigned long size, unsigned long step)
  77. {
  78. struct timespec start, finish;
  79. unsigned long index;
  80. long long nsec;
  81. clock_gettime(CLOCK_MONOTONIC, &start);
  82. for (index = 0 ; index < size ; index += step)
  83. item_delete(root, index);
  84. clock_gettime(CLOCK_MONOTONIC, &finish);
  85. nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
  86. (finish.tv_nsec - start.tv_nsec);
  87. printv(2, "Size: %8ld, step: %8ld, deletion: %16lld ns\n",
  88. size, step, nsec);
  89. }
  90. static void benchmark_size(unsigned long size, unsigned long step)
  91. {
  92. RADIX_TREE(tree, GFP_KERNEL);
  93. long long normal, tagged;
  94. benchmark_insert(&tree, size, step);
  95. benchmark_tagging(&tree, size, step);
  96. tagged = benchmark_iter(&tree, true);
  97. normal = benchmark_iter(&tree, false);
  98. printv(2, "Size: %8ld, step: %8ld, tagged iteration: %8lld ns\n",
  99. size, step, tagged);
  100. printv(2, "Size: %8ld, step: %8ld, normal iteration: %8lld ns\n",
  101. size, step, normal);
  102. benchmark_delete(&tree, size, step);
  103. item_kill_tree(&tree);
  104. rcu_barrier();
  105. }
  106. void benchmark(void)
  107. {
  108. unsigned long size[] = {1 << 10, 1 << 20, 0};
  109. unsigned long step[] = {1, 2, 7, 15, 63, 64, 65,
  110. 128, 256, 512, 12345, 0};
  111. int c, s;
  112. printv(1, "starting benchmarks\n");
  113. printv(1, "RADIX_TREE_MAP_SHIFT = %d\n", RADIX_TREE_MAP_SHIFT);
  114. for (c = 0; size[c]; c++)
  115. for (s = 0; step[s]; s++)
  116. benchmark_size(size[c], step[s]);
  117. }