interval_tree_test.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #include <linux/module.h>
  3. #include <linux/moduleparam.h>
  4. #include <linux/interval_tree.h>
  5. #include <linux/random.h>
  6. #include <linux/slab.h>
  7. #include <asm/timex.h>
  8. #define __param(type, name, init, msg) \
  9. static type name = init; \
  10. module_param(name, type, 0444); \
  11. MODULE_PARM_DESC(name, msg);
  12. __param(int, nnodes, 100, "Number of nodes in the interval tree");
  13. __param(int, perf_loops, 1000, "Number of iterations modifying the tree");
  14. __param(int, nsearches, 100, "Number of searches to the interval tree");
  15. __param(int, search_loops, 1000, "Number of iterations searching the tree");
  16. __param(bool, search_all, false, "Searches will iterate all nodes in the tree");
  17. __param(uint, max_endpoint, ~0, "Largest value for the interval's endpoint");
  18. static struct rb_root_cached root = RB_ROOT_CACHED;
  19. static struct interval_tree_node *nodes = NULL;
  20. static u32 *queries = NULL;
  21. static struct rnd_state rnd;
  22. static inline unsigned long
  23. search(struct rb_root_cached *root, unsigned long start, unsigned long last)
  24. {
  25. struct interval_tree_node *node;
  26. unsigned long results = 0;
  27. for (node = interval_tree_iter_first(root, start, last); node;
  28. node = interval_tree_iter_next(node, start, last))
  29. results++;
  30. return results;
  31. }
  32. static void init(void)
  33. {
  34. int i;
  35. for (i = 0; i < nnodes; i++) {
  36. u32 b = (prandom_u32_state(&rnd) >> 4) % max_endpoint;
  37. u32 a = (prandom_u32_state(&rnd) >> 4) % b;
  38. nodes[i].start = a;
  39. nodes[i].last = b;
  40. }
  41. /*
  42. * Limit the search scope to what the user defined.
  43. * Otherwise we are merely measuring empty walks,
  44. * which is pointless.
  45. */
  46. for (i = 0; i < nsearches; i++)
  47. queries[i] = (prandom_u32_state(&rnd) >> 4) % max_endpoint;
  48. }
  49. static int interval_tree_test_init(void)
  50. {
  51. int i, j;
  52. unsigned long results;
  53. cycles_t time1, time2, time;
  54. nodes = kmalloc_array(nnodes, sizeof(struct interval_tree_node),
  55. GFP_KERNEL);
  56. if (!nodes)
  57. return -ENOMEM;
  58. queries = kmalloc_array(nsearches, sizeof(int), GFP_KERNEL);
  59. if (!queries) {
  60. kfree(nodes);
  61. return -ENOMEM;
  62. }
  63. printk(KERN_ALERT "interval tree insert/remove");
  64. prandom_seed_state(&rnd, 3141592653589793238ULL);
  65. init();
  66. time1 = get_cycles();
  67. for (i = 0; i < perf_loops; i++) {
  68. for (j = 0; j < nnodes; j++)
  69. interval_tree_insert(nodes + j, &root);
  70. for (j = 0; j < nnodes; j++)
  71. interval_tree_remove(nodes + j, &root);
  72. }
  73. time2 = get_cycles();
  74. time = time2 - time1;
  75. time = div_u64(time, perf_loops);
  76. printk(" -> %llu cycles\n", (unsigned long long)time);
  77. printk(KERN_ALERT "interval tree search");
  78. for (j = 0; j < nnodes; j++)
  79. interval_tree_insert(nodes + j, &root);
  80. time1 = get_cycles();
  81. results = 0;
  82. for (i = 0; i < search_loops; i++)
  83. for (j = 0; j < nsearches; j++) {
  84. unsigned long start = search_all ? 0 : queries[j];
  85. unsigned long last = search_all ? max_endpoint : queries[j];
  86. results += search(&root, start, last);
  87. }
  88. time2 = get_cycles();
  89. time = time2 - time1;
  90. time = div_u64(time, search_loops);
  91. results = div_u64(results, search_loops);
  92. printk(" -> %llu cycles (%lu results)\n",
  93. (unsigned long long)time, results);
  94. kfree(queries);
  95. kfree(nodes);
  96. return -EAGAIN; /* Fail will directly unload the module */
  97. }
  98. static void interval_tree_test_exit(void)
  99. {
  100. printk(KERN_ALERT "test exit\n");
  101. }
  102. module_init(interval_tree_test_init)
  103. module_exit(interval_tree_test_exit)
  104. MODULE_LICENSE("GPL");
  105. MODULE_AUTHOR("Michel Lespinasse");
  106. MODULE_DESCRIPTION("Interval Tree test");