Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

rspamd_heap_test.c 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "config.h"
  17. #include "rspamd.h"
  18. #include "heap.h"
  19. #include "ottery.h"
  20. static const guint niter = 100500;
  21. static const guint nrem = 100;
  22. static inline
  23. struct rspamd_min_heap_elt *
  24. new_elt (guint pri)
  25. {
  26. struct rspamd_min_heap_elt *elt;
  27. elt = g_slice_alloc0 (sizeof (*elt));
  28. elt->pri = pri;
  29. return elt;
  30. }
  31. static gdouble
  32. heap_nelts_test (guint nelts)
  33. {
  34. struct rspamd_min_heap *heap;
  35. struct rspamd_min_heap_elt *elts;
  36. gdouble t1, t2;
  37. guint i;
  38. heap = rspamd_min_heap_create (nelts);
  39. /* Preallocate all elts */
  40. elts = g_slice_alloc (sizeof (*elts) * nelts);
  41. for (i = 0; i < nelts; i ++) {
  42. elts[i].pri = ottery_rand_uint32 () % G_MAXINT32 + 1;
  43. elts[i].idx = 0;
  44. }
  45. t1 = rspamd_get_virtual_ticks ();
  46. for (i = 0; i < nelts; i ++) {
  47. rspamd_min_heap_push (heap, &elts[i]);
  48. }
  49. for (i = 0; i < nelts; i ++) {
  50. (void)rspamd_min_heap_pop (heap);
  51. }
  52. t2 = rspamd_get_virtual_ticks ();
  53. g_slice_free1 (sizeof (*elts) * nelts, elts);
  54. rspamd_min_heap_destroy (heap);
  55. return (t2 - t1);
  56. }
  57. void
  58. rspamd_heap_test_func (void)
  59. {
  60. struct rspamd_min_heap *heap;
  61. struct rspamd_min_heap_elt *elt, *telt;
  62. guint i;
  63. guint prev;
  64. gdouble t[16];
  65. /* Push + update */
  66. heap = rspamd_min_heap_create (32);
  67. elt = new_elt (2);
  68. elt->data = GINT_TO_POINTER (1);
  69. rspamd_min_heap_push (heap, elt);
  70. elt = new_elt (3);
  71. elt->data = GINT_TO_POINTER (2);
  72. rspamd_min_heap_push (heap, elt);
  73. elt = new_elt (4);
  74. elt->data = GINT_TO_POINTER (3);
  75. rspamd_min_heap_push (heap, elt);
  76. rspamd_min_heap_update_elt (heap, elt, 0);
  77. elt = rspamd_min_heap_pop (heap);
  78. g_assert (elt->data == GINT_TO_POINTER (3));
  79. rspamd_min_heap_destroy (heap);
  80. /* Push + remove */
  81. heap = rspamd_min_heap_create (32);
  82. elt = new_elt (2);
  83. elt->data = GINT_TO_POINTER (1);
  84. rspamd_min_heap_push (heap, elt);
  85. rspamd_min_heap_remove_elt (heap, elt);
  86. elt = new_elt (3);
  87. elt->data = GINT_TO_POINTER (2);
  88. rspamd_min_heap_push (heap, elt);
  89. elt = rspamd_min_heap_pop (heap);
  90. g_assert (elt->data == GINT_TO_POINTER (2));
  91. elt = rspamd_min_heap_pop (heap);
  92. g_assert (elt == NULL);
  93. /* Push + push + remove + pop */
  94. elt = new_elt (2);
  95. elt->data = GINT_TO_POINTER (1);
  96. rspamd_min_heap_push (heap, elt);
  97. telt = elt;
  98. elt = new_elt (3);
  99. elt->data = GINT_TO_POINTER (2);
  100. rspamd_min_heap_push (heap, elt);
  101. rspamd_min_heap_remove_elt (heap, telt);
  102. elt = rspamd_min_heap_pop (heap);
  103. g_assert (elt->data == GINT_TO_POINTER (2));
  104. rspamd_min_heap_destroy (heap);
  105. /* Bulk test */
  106. heap = rspamd_min_heap_create (32);
  107. for (i = 100; i > 0; i --) {
  108. elt = new_elt (i - 1);
  109. rspamd_min_heap_push (heap, elt);
  110. }
  111. for (i = 0; i < 100; i ++) {
  112. elt = rspamd_min_heap_pop (heap);
  113. g_assert (elt->pri == i);
  114. }
  115. rspamd_min_heap_destroy (heap);
  116. /* Fuzz test */
  117. heap = rspamd_min_heap_create (128);
  118. /* Add */
  119. for (i = 0; i < niter; i ++) {
  120. elt = new_elt (ottery_rand_uint32 () % G_MAXINT32 + 1);
  121. rspamd_min_heap_push (heap, elt);
  122. }
  123. /* Remove */
  124. for (i = 0; i < nrem; i ++) {
  125. elt = rspamd_min_heap_index (heap, ottery_rand_uint32 () % niter);
  126. rspamd_min_heap_remove_elt (heap, elt);
  127. }
  128. /* Update */
  129. for (i = 0; i < niter / 10; i ++) {
  130. elt = rspamd_min_heap_index (heap, ottery_rand_uint32 () % (niter - nrem));
  131. rspamd_min_heap_update_elt (heap, elt,
  132. ottery_rand_uint32 () % G_MAXINT32 + 1);
  133. }
  134. prev = 0;
  135. /* Pop and check invariant */
  136. for (i = 0; i < niter - nrem; i ++) {
  137. elt = rspamd_min_heap_pop (heap);
  138. if (prev != 0) {
  139. g_assert (elt->pri >= prev);
  140. }
  141. prev = elt->pri;
  142. }
  143. rspamd_min_heap_destroy (heap);
  144. /* Complexity test (should be O(n * logn) */
  145. for (i = 1; i <= G_N_ELEMENTS (t); i ++) {
  146. t[i - 1] = heap_nelts_test (0x1 << (i + 4));
  147. }
  148. for (i = 1; i <= G_N_ELEMENTS (t); i ++) {
  149. rspamd_printf ("Elements: %d, time: %.4f\n", 0x1 << (i + 4), t[i - 1]);
  150. }
  151. }