The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
minmax_heap_tests.c
Go to the documentation of this file.
1#include "acutest.h"
2#include <freeradius-devel/util/heap.h>
3#include <freeradius-devel/util/rand.h>
4#include <freeradius-devel/util/time.h>
5
6#include "../minmax_heap.c"
7
8typedef struct {
9 unsigned int data;
10 fr_minmax_heap_index_t idx; /* for the heap */
11 bool visited;
13
15{
16 minmax_heap_t *h = *hp;
17
18 for (unsigned int i = 1; i <= h->num_elements; i++) if (h->p[i] == data) return true;
19
20 return false;
21}
22
23static int8_t minmax_heap_cmp(void const *one, void const *two)
24{
25 minmax_heap_thing const *a = one, *b = two;
26
27 return CMP_PREFER_SMALLER(a->data, b->data);
28}
29
30#if 0
31#define is_power_of_2(_n) !((_n) & ((_n) - 1))
32/*
33 * A simple minmax heap dump function, specific to minmax_heap_thing and
34 * intended for use only with small heaps. It only shows the data members
35 * in the order they appear in the array, ignoring the unused zeroeth
36 * entry and printing a vertical bar before the start of each successive level.
37 */
38static void minmax_heap_dump(fr_minmax_heap_t *hp)
39{
40 minmax_heap_t *h = *hp;
41 unsigned int num_elements = h->num_elements;
42
43 fprintf(stderr, "%3u: ", num_elements);
44
45 for (fr_minmax_heap_index_t i = 1; i <= num_elements; i++) {
46 if (is_power_of_2(i)) fprintf(stderr, "|");
47 fprintf(stderr, "%6u", ((minmax_heap_thing *)(h->p[i]))->data);
48 }
49 fprintf(stderr, "\n");
50}
51#endif
52
53static void populate_values(minmax_heap_thing values[], unsigned int len)
54{
55 unsigned int i;
56 fr_fast_rand_t rand_ctx;
57
58 for (i = 0; i < len; i++) {
59 values[i].data = i;
60 values[i].idx = 0;
61 values[i].visited = false;
62 }
63
64 /* shuffle values before insertion, so the heap has to work to give them back in order */
65 rand_ctx.a = fr_rand();
66 rand_ctx.b = fr_rand();
67
68 for (i = 0; i < len; i++) {
69 unsigned int j = fr_fast_rand(&rand_ctx) % len;
70 int temp = values[i].data;
71
72 values[i].data = values[j].data;
73 values[j].data = temp;
74 }
75}
76
77#define NVALUES 20
78static void minmax_heap_test_basic(void)
79{
80 unsigned int i;
83
85 TEST_CHECK(hp != NULL);
86
87 populate_values(values, NVALUES);
88
89 /*
90 * minmax heaps can get the minimum value...
91 */
92 for (i = 0; i < NVALUES; i++) {
93 TEST_CHECK(fr_minmax_heap_insert(hp, &values[i]) >= 0);
95 }
96
97 for (i = 0; i < NVALUES; i++) {
99
100 TEST_CHECK(value != NULL);
102 TEST_CHECK(value->data == i);
103 TEST_MSG("iteration %u, popped %u", i, value->data);
104 }
105
106 /*
107 * ...or the maximum value.
108 */
109 for (i = 0; i < NVALUES; i++) {
110 TEST_CHECK(fr_minmax_heap_insert(hp, &values[i]) >= 0);
112 }
113
114 for (i = NVALUES; i-- > 0; ) {
116
117 TEST_CHECK(value != NULL);
119 TEST_CHECK(value->data == i);
120 TEST_MSG("iteration %u, popped %u", NVALUES - 1 - i, value->data);
121 }
122
123 talloc_free(hp);
124}
125
126#define MINMAX_HEAP_TEST_SIZE (4096)
127
128static void minmax_heap_test(int skip)
129{
131 int i;
132 minmax_heap_thing *array;
133 int left;
134 int ret;
135 fr_fast_rand_t rand_ctx;
136
137 rand_ctx.a = fr_rand();
138 rand_ctx.b = fr_rand();
139
141 TEST_CHECK(hp != NULL);
142
143 array = talloc_zero_array(hp, minmax_heap_thing, MINMAX_HEAP_TEST_SIZE);
144
145 /*
146 * Initialise random values
147 */
148 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) array[i].data = fr_fast_rand(&rand_ctx) % 65537;
149
150 TEST_CASE("insertions");
151 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) {
153 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
154 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
155
156 TEST_CHECK(minmax_heap_contains(hp, &array[i]));
157 TEST_MSG("element %i inserted but not in heap", i);
158 }
159
160 TEST_CASE("deletions");
161 {
162 int entry;
163
164 for (i = 0; i < MINMAX_HEAP_TEST_SIZE / skip; i++) {
165 entry = i * skip;
166
168 TEST_CHECK(array[entry].idx != 0);
169 TEST_MSG("element %i removed out of order", entry);
170
171 TEST_CHECK((ret = fr_minmax_heap_extract(hp, &array[entry])) >= 0);
172 TEST_MSG("element %i removal failed, returned %i - %s", entry, ret, fr_strerror());
173
174 TEST_CHECK(!minmax_heap_contains(hp, &array[entry]));
175 TEST_MSG("element %i removed but still in heap", entry);
176
177 TEST_CHECK(array[entry].idx == 0);
178 TEST_MSG("element %i removed out of order", entry);
179 }
180 }
181
183 for (i = 0; i < left; i++) {
185
187 TEST_CHECK((t = fr_minmax_heap_min_peek(hp)) != NULL);
188 TEST_MSG("expected %i elements remaining in the heap", left - i);
189
191 TEST_MSG("failed extracting %i", i);
192 }
193
194 TEST_CHECK((ret = fr_minmax_heap_num_elements(hp)) == 0);
195 TEST_MSG("%i elements remaining", ret);
196
197 talloc_free(hp);
198}
199
200/*
201 * minmax heaps can do anything heaps can do, so let's make sure we have
202 * a (proper!) superset of the heap tests.
203 */
204
205static void minmax_heap_test_skip_0(void)
206{
208}
209
210static void minmax_heap_test_skip_2(void)
211{
213}
214
216{
218}
219
220#define BURN_IN_OPS (10000000)
221
222static void minmax_heap_burn_in(void)
223{
224 fr_minmax_heap_t *hp = NULL;
225 minmax_heap_thing *array = NULL;
226 fr_fast_rand_t rand_ctx;
227 int insert_count = 0;
228
229 rand_ctx.a = fr_rand();
230 rand_ctx.b = fr_rand();
231
232 array = calloc(BURN_IN_OPS, sizeof(minmax_heap_thing));
233 for (unsigned int i = 0; i < BURN_IN_OPS; i++) array[i].data = fr_fast_rand(&rand_ctx) % 65537;
234
236 TEST_CHECK(hp != NULL);
237
238 for (unsigned int i = 0; i < BURN_IN_OPS; i++) {
239 minmax_heap_thing *ret_thing = NULL;
240 int ret_insert = -1;
241
242 if (fr_minmax_heap_num_elements(hp) == 0) {
243 insert:
244 TEST_CHECK((ret_insert = fr_minmax_heap_insert(hp, &array[insert_count])) >= 0);
245 insert_count++;
246 } else {
247 switch (fr_fast_rand(&rand_ctx) % 5) {
248 case 0: /* insert */
249 goto insert;
250
251 case 1: /* min pop */
252 ret_thing = fr_minmax_heap_min_pop(hp);
253 TEST_CHECK(ret_thing != NULL);
254 break;
255 case 2: /* min peek */
256 ret_thing = fr_minmax_heap_min_peek(hp);
257 TEST_CHECK(ret_thing != NULL);
258 break;
259 case 3: /* max pop */
260 ret_thing = fr_minmax_heap_max_pop(hp);
261 TEST_CHECK(ret_thing != NULL);
262 break;
263 case 4: /* max peek */
264 ret_thing = fr_minmax_heap_max_peek(hp);
265 TEST_CHECK(ret_thing != NULL);
266 break;
267 }
268 }
269 }
270
271 talloc_free(hp);
272 free(array);
273}
274
275#define MINMAX_HEAP_CYCLE_SIZE (1600000)
276
277static void minmax_heap_test_order(void)
278{
280 int i;
281 minmax_heap_thing *array;
282 minmax_heap_thing *thing, *prev = NULL;
283 unsigned int data;
284 unsigned int count;
285 int ret;
286 fr_fast_rand_t rand_ctx;
287
288 rand_ctx.a = fr_rand();
289 rand_ctx.b = fr_rand();
290
292 TEST_CHECK(hp != NULL);
293
294 array = talloc_zero_array(hp, minmax_heap_thing, MINMAX_HEAP_TEST_SIZE);
295
296 /*
297 * Initialise random values
298 */
299 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) array[i].data = fr_fast_rand(&rand_ctx) % 65537;
300
301 TEST_CASE("insertions for min");
302 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) {
303 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
304 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
305
306 TEST_CHECK(minmax_heap_contains(hp, &array[i]));
307 TEST_MSG("element %i inserted but not in heap", i);
308 }
309
310 TEST_CASE("min ordering");
311
312 count = 0;
313 data = 0;
314 prev = NULL;
315 while ((thing = fr_minmax_heap_min_pop(hp))) {
316 TEST_CHECK(thing->data >= data);
317 TEST_MSG("Expected data >= %u, got %u", data, thing->data);
318 if (thing->data >= data) data = thing->data;
319 TEST_CHECK(thing != prev);
320 prev = thing;
321 count++;
322 }
323
325
326 TEST_CASE("insertions for max");
327 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) {
328 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
329 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
330
331 TEST_CHECK(minmax_heap_contains(hp, &array[i]));
332 TEST_MSG("element %i inserted but not in heap", i);
333 }
334
335 TEST_CASE("max ordering");
336
337 count = 0;
338 data = UINT_MAX;
339 prev = NULL;
340 while ((thing = fr_minmax_heap_max_pop(hp))) {
341 TEST_CHECK(thing->data <= data);
342 TEST_MSG("Expected data >= %u, got %u", data, thing->data);
343 if (thing->data <= data) data = thing->data;
344 TEST_CHECK(thing != prev);
345 prev = thing;
346 count++;
347 }
348
350
351 talloc_free(hp);
352}
353
354static CC_HINT(noinline) minmax_heap_thing *array_pop(minmax_heap_thing **array, unsigned int count)
355{
356 minmax_heap_thing *low = NULL;
357 unsigned int idx = 0;
358
359 for (unsigned int j = 0; j < count; j++) {
360 if (!array[j]) continue;
361
362 if (!low || (minmax_heap_cmp(array[j], low) < 0)) {
363 idx = j;
364 low = array[j];
365 }
366 }
367 if (low) array[idx] = NULL;
368
369 return low;
370}
371
372/** Benchmarks for minmax heaps vs heaps when used as queues
373 *
374 */
375static void queue_cmp(unsigned int count)
376{
377 fr_minmax_heap_t *minmax;
378 fr_heap_t *hp;
379
380 minmax_heap_thing *values;
381
382 unsigned int i;
383
384 values = talloc_array(NULL, minmax_heap_thing, count);
385
386 /*
387 * Check times for minmax heap alloc, insert, pop
388 */
389 {
390 fr_time_t start_alloc, end_alloc, start_insert, end_insert, start_pop, end_pop, end_pop_first = fr_time_wrap(0);
391
392 populate_values(values, count);
393
394 start_alloc = fr_time();
396 end_alloc = fr_time();
397 TEST_CHECK(minmax != NULL);
398
399 start_insert = fr_time();
400 for (i = 0; i < count; i++) (void) fr_minmax_heap_insert(minmax, &values[i]);
401 end_insert = fr_time();
402
403 start_pop = fr_time();
404 for (i = 0; i < count; i++) {
405 TEST_CHECK(fr_minmax_heap_min_pop(minmax) != NULL);
406 if (i == 0) end_pop_first = fr_time();
407
408 TEST_MSG("expected %u elements remaining in the minmax heap", count - i);
409 TEST_MSG("failed extracting %u", i);
410 }
411 end_pop = fr_time();
412
413 TEST_MSG_ALWAYS("\nminmax heap size: %u\n", count);
414 TEST_MSG_ALWAYS("alloc: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_alloc, start_alloc)));
415 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_insert, start_insert)));
416 TEST_MSG_ALWAYS("pop-first: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop_first, start_pop)));
417 TEST_MSG_ALWAYS("pop: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop, start_pop)));
418 talloc_free(minmax);
419 }
420
421 /*
422 * Check times for heap alloc, insert, pop
423 */
424 {
425 fr_time_t start_alloc, end_alloc, start_insert, end_insert, start_pop, end_pop, end_pop_first = fr_time_min();
426
427 populate_values(values, count);
428
429 start_alloc = fr_time();
431 end_alloc = fr_time();
432 TEST_CHECK(hp != NULL);
433
434 start_insert = fr_time();
435 for (i = 0; i < count; i++) fr_heap_insert(&hp, &values[i]);
436 end_insert = fr_time();
437
438 start_pop = fr_time();
439 for (i = 0; i < count; i++) {
440 TEST_CHECK(fr_heap_pop(&hp) != NULL);
441 if (i == 0) end_pop_first = fr_time();
442
443 TEST_MSG("expected %u elements remaining in the heap", count - i);
444 TEST_MSG("failed extracting %u", i);
445 }
446 end_pop = fr_time();
447
448 TEST_MSG_ALWAYS("\nheap size: %u\n", count);
449 TEST_MSG_ALWAYS("alloc: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_alloc, start_alloc)));
450 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_insert, start_insert)));
451 TEST_MSG_ALWAYS("pop-first: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop_first, start_pop)));
452 TEST_MSG_ALWAYS("pop: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop, start_pop)));
453
454 talloc_free(hp);
455 }
456
457 /*
458 * Array
459 */
460 {
461 minmax_heap_thing **array;
462 fr_time_t start_alloc, end_alloc, start_insert, end_insert, start_pop, end_pop, end_pop_first;
463
464 populate_values(values, count);
465 end_pop_first = fr_time_min();
466
467 start_alloc = fr_time();
468 array = talloc_array(NULL, minmax_heap_thing *, count);
469 end_alloc = fr_time();
470
471 start_insert = fr_time();
472 for (i = 0; i < count; i++) array[i] = &values[i];
473 end_insert = fr_time();
474
475 start_pop = fr_time();
476 for (i = 0; i < count; i++) {
477 TEST_CHECK(array_pop(array, count) != NULL);
478 if (i == 0) end_pop_first = fr_time();
479 }
480 end_pop = fr_time();
481
482 TEST_MSG_ALWAYS("\narray size: %u\n", count);
483 TEST_MSG_ALWAYS("alloc: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_alloc, start_alloc)));
484 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_insert, start_insert)));
485 TEST_MSG_ALWAYS("pop-first: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop_first, start_pop)));
486 TEST_MSG_ALWAYS("pop: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop, start_pop)));
487
488 talloc_free(array);
489 }
490
491 talloc_free(values);
492}
493
494static void queue_cmp_10(void)
495{
496 queue_cmp(10);
497}
498
499static void queue_cmp_50(void)
500{
501 queue_cmp(50);
502}
503
504static void queue_cmp_100(void)
505{
506 queue_cmp(100);
507}
508
509static void queue_cmp_1000(void)
510{
511 queue_cmp(1000);
512}
513
514static void minmax_heap_cycle(void)
515{
517 int i;
518 minmax_heap_thing *array;
519 int to_remove;
520 int inserted, removed;
521 int ret;
522 fr_time_t start_insert, start_remove, start_swap, end;
523 fr_fast_rand_t rand_ctx;
524
525 rand_ctx.a = fr_rand();
526 rand_ctx.b = fr_rand();
527
529 TEST_CHECK(hp != NULL);
530
531 array = calloc(MINMAX_HEAP_CYCLE_SIZE, sizeof(minmax_heap_thing));
532
533 /*
534 * Initialise random values
535 */
536 for (i = 0; i < MINMAX_HEAP_CYCLE_SIZE; i++) array[i].data = fr_fast_rand(&rand_ctx) % 65537;
537
538 start_insert = fr_time();
539 TEST_CASE("insertions");
540 for (i = 0; i < MINMAX_HEAP_CYCLE_SIZE; i++) {
541 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
542 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
543 }
545
546 TEST_CASE("pop");
547
548 /*
549 * Remove a random number of elements from the heap
550 */
551 to_remove = fr_minmax_heap_num_elements(hp) / 2;
552 start_remove = fr_time();
553 for (i = 0; i < to_remove; i++) {
555
556 TEST_CHECK((t = fr_minmax_heap_min_peek(hp)) != NULL);
557 TEST_MSG("expected %i elements remaining in the heap", to_remove - i);
558
560 TEST_MSG("failed extracting %i - %s", i, fr_strerror());
561 }
562
563 /*
564 * Now swap the inserted and removed set creating churn
565 */
566 start_swap = fr_time();
567 inserted = 0;
568 removed = 0;
569
570 for (i = 0; i < MINMAX_HEAP_CYCLE_SIZE; i++) {
571 if (!fr_minmax_heap_entry_inserted(array[i].idx)) {
572 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
573 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
574 inserted++;
575 } else {
576 TEST_CHECK((ret = fr_minmax_heap_extract(hp, &array[i])) >= 0);
577 TEST_MSG("element %i removal failed, returned %i - %s", i, ret, fr_strerror());
578 removed++;
579 }
580 }
581
582 TEST_CHECK(removed == (MINMAX_HEAP_CYCLE_SIZE - to_remove));
583 TEST_MSG("expected %i", MINMAX_HEAP_CYCLE_SIZE - to_remove);
584 TEST_MSG("got %i", removed);
585
586 TEST_CHECK(inserted == to_remove);
587 TEST_MSG("expected %i", to_remove);
588 TEST_MSG("got %i", inserted);
589
590 end = fr_time();
591
592 TEST_MSG_ALWAYS("\ncycle size: %d\n", MINMAX_HEAP_CYCLE_SIZE);
593 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(start_remove, start_insert)));
594 TEST_MSG_ALWAYS("extract: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(start_swap, start_remove)));
595 TEST_MSG_ALWAYS("swap: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end, start_swap)));
596
597 talloc_free(hp);
598 free(array);
599}
600
601static void minmax_heap_iter(void)
602{
606 unsigned int total;
607
609 TEST_CHECK(hp != NULL);
610
611 populate_values(values, NUM_ELEMENTS(values));
612
613 for (unsigned int i = 0; i < NUM_ELEMENTS(values); i++) (void) fr_minmax_heap_insert(hp, &values[i]);
614
615 data = fr_minmax_heap_iter_init(hp, &iter);
616
617 for (unsigned int i = 0; i < NUM_ELEMENTS(values); i++, data = fr_minmax_heap_iter_next(hp, &iter)) {
618 TEST_CHECK(data != NULL);
619 TEST_CHECK(!data->visited);
620 TEST_CHECK(data->idx > 0);
621 data->visited = true;
622 }
623
624 TEST_CHECK(data == NULL);
625
626 total = 0;
628 total += item->data;
629 }}
630 TEST_CHECK(total == 190);
631
633}
634
636 /*
637 * Basic tests
638 */
639 { "minmax_heap_test_basic", minmax_heap_test_basic },
640 { "minmax_heap_test_skip_0", minmax_heap_test_skip_0 },
641 { "minmax_heap_test_skip_2", minmax_heap_test_skip_2 },
642 { "minmax_heap_test_skip_10", minmax_heap_test_skip_10 },
643 { "minmax_heap_test_order", minmax_heap_test_order },
644 { "minmax_heap_burn_in", minmax_heap_burn_in },
645 { "minmax_heap_cycle", minmax_heap_cycle },
646 { "minmax_heap_iter", minmax_heap_iter },
647 { "queue_cmp_10", queue_cmp_10 },
648 { "queue_cmp_50", queue_cmp_50 },
649 { "queue_cmp_100", queue_cmp_100 },
650 { "queue_cmp_1000", queue_cmp_1000 },
652};
653
#define TEST_MSG_ALWAYS(...)
Definition acutest.h:224
#define TEST_CHECK(cond)
Definition acutest.h:87
#define TEST_CASE(name)
Definition acutest.h:186
#define TEST_TERMINATOR
Definition acutest.h:64
#define TEST_MSG(...)
Definition acutest.h:217
#define CMP_PREFER_SMALLER(_a, _b)
Evaluates to +1 for a > b, and -1 for a < b.
Definition build.h:104
#define NUM_ELEMENTS(_t)
Definition build.h:339
Test enumeration values.
Definition dict_test.h:92
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
Definition heap.c:146
void * fr_heap_pop(fr_heap_t **hp)
Remove a node from the heap.
Definition heap.c:325
#define fr_heap_alloc(_ctx, _cmp, _type, _field, _init)
Creates a heap that can be used with non-talloced elements.
Definition heap.h:100
The main heap structure.
Definition heap.h:66
free(array)
#define fr_time()
Definition event.c:60
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
Definition lst.c:122
#define is_power_of_2(_n)
Definition lst.c:50
void * fr_minmax_heap_max_pop(fr_minmax_heap_t *hp)
int fr_minmax_heap_insert(fr_minmax_heap_t *hp, void *data)
void * fr_minmax_heap_iter_next(fr_minmax_heap_t *hp, fr_minmax_heap_iter_t *iter)
Get the next entry in a minmax heap.
void * p[]
Array of nodes.
Definition minmax_heap.c:62
void * fr_minmax_heap_min_peek(fr_minmax_heap_t *hp)
void * fr_minmax_heap_min_pop(fr_minmax_heap_t *hp)
void * fr_minmax_heap_max_peek(fr_minmax_heap_t *hp)
unsigned int fr_minmax_heap_num_elements(fr_minmax_heap_t *hp)
Return the number of elements in the minmax heap.
void * fr_minmax_heap_iter_init(fr_minmax_heap_t *hp, fr_minmax_heap_iter_t *iter)
Iterate over entries in a minmax heap.
int fr_minmax_heap_extract(fr_minmax_heap_t *hp, void *data)
unsigned int num_elements
Number of nodes used.
Definition minmax_heap.c:57
#define FR_MINMAX_HEAP_VERIFY(_hp)
#define fr_minmax_heap_foreach(_hp, _type, _data)
Iterate over the contents of a minmax_heap.
static bool fr_minmax_heap_entry_inserted(fr_minmax_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
Definition minmax_heap.h:93
unsigned int fr_minmax_heap_iter_t
Definition minmax_heap.h:38
#define fr_minmax_heap_alloc(_ctx, _cmp, _type, _field, _init)
Creates a minmax heap that can be used with non-talloced elements.
Definition minmax_heap.h:70
unsigned int fr_minmax_heap_index_t
Definition minmax_heap.h:37
static void queue_cmp_100(void)
static void queue_cmp(unsigned int count)
Benchmarks for minmax heaps vs heaps when used as queues.
#define MINMAX_HEAP_TEST_SIZE
static bool minmax_heap_contains(fr_minmax_heap_t *hp, void *data)
#define NVALUES
#define MINMAX_HEAP_CYCLE_SIZE
#define BURN_IN_OPS
static void queue_cmp_50(void)
static void minmax_heap_test_order(void)
static void minmax_heap_test_skip_2(void)
fr_minmax_heap_index_t idx
static void minmax_heap_test_skip_0(void)
static void minmax_heap_cycle(void)
static void queue_cmp_1000(void)
static void queue_cmp_10(void)
static void minmax_heap_test_skip_10(void)
static void minmax_heap_test(int skip)
static void minmax_heap_test_basic(void)
static void minmax_heap_burn_in(void)
static void populate_values(minmax_heap_thing values[], unsigned int len)
static minmax_heap_thing * array_pop(minmax_heap_thing **array, unsigned int count)
talloc_free(hp)
static int8_t minmax_heap_cmp(void const *one, void const *two)
static void minmax_heap_iter(void)
uint32_t fr_fast_rand(fr_fast_rand_t *ctx)
Definition rand.c:279
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:105
uint32_t b
Definition rand.h:55
uint32_t a
Definition rand.h:55
Smaller fast random number generator.
Definition rand.h:54
return count
Definition module.c:155
#define fr_time_min()
Definition time.h:144
#define fr_time_wrap(_time)
Definition time.h:145
static int64_t fr_time_delta_to_usec(fr_time_delta_t delta)
Definition time.h:632
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition time.h:229
"server local" time.
Definition time.h:69
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
static fr_slen_t data
Definition value.h:1340