The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
minmax_heap_tests.c
Go to the documentation of this file.
1#include <freeradius-devel/util/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{
82
84 TEST_CHECK(hp != NULL);
85
86 populate_values(values, NVALUES);
87
88 /*
89 * minmax heaps can get the minimum value...
90 */
91 for (unsigned int i = 0; i < NVALUES; i++) {
92 TEST_CHECK(fr_minmax_heap_insert(hp, &values[i]) >= 0);
94 }
95
96 for (unsigned int i = 0; i < NVALUES; i++) {
98
99 TEST_CHECK(value != NULL);
101 TEST_CHECK(value->data == i);
102 TEST_MSG("iteration %u, popped %u", i, value->data);
103 }
104
105 /*
106 * ...or the maximum value.
107 */
108 for (unsigned int i = 0; i < NVALUES; i++) {
109 TEST_CHECK(fr_minmax_heap_insert(hp, &values[i]) >= 0);
111 }
112
113 for (unsigned int i = NVALUES; --i > 0; ) {
115
116 TEST_CHECK(value != NULL);
118 TEST_CHECK(value->data == i);
119 TEST_MSG("iteration %u, popped %u", NVALUES - 1 - i, value->data);
120 }
121
122 talloc_free(hp);
123}
124
125#define MINMAX_HEAP_TEST_SIZE (4096)
126
127static void minmax_heap_test(int skip)
128{
130 int i;
131 minmax_heap_thing *array;
132 int left;
133 int ret;
134 fr_fast_rand_t rand_ctx;
135
136 rand_ctx.a = fr_rand();
137 rand_ctx.b = fr_rand();
138
140 TEST_CHECK(hp != NULL);
141
142 array = talloc_zero_array(hp, minmax_heap_thing, MINMAX_HEAP_TEST_SIZE);
143
144 /*
145 * Initialise random values
146 */
147 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) array[i].data = fr_fast_rand(&rand_ctx) % 65537;
148
149 TEST_CASE("insertions");
150 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) {
152 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
153 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
154
155 TEST_CHECK(minmax_heap_contains(hp, &array[i]));
156 TEST_MSG("element %i inserted but not in heap", i);
157 }
158
159 TEST_CASE("deletions");
160 {
161 int entry;
162
163 for (i = 0; i < MINMAX_HEAP_TEST_SIZE / skip; i++) {
164 entry = i * skip;
165
167 TEST_CHECK(array[entry].idx != 0);
168 TEST_MSG("element %i removed out of order", entry);
169
170 TEST_CHECK((ret = fr_minmax_heap_extract(hp, &array[entry])) >= 0);
171 TEST_MSG("element %i removal failed, returned %i - %s", entry, ret, fr_strerror());
172
173 TEST_CHECK(!minmax_heap_contains(hp, &array[entry]));
174 TEST_MSG("element %i removed but still in heap", entry);
175
176 TEST_CHECK(array[entry].idx == 0);
177 TEST_MSG("element %i removed out of order", entry);
178 }
179 }
180
182 for (i = 0; i < left; i++) {
184
186 TEST_CHECK((t = fr_minmax_heap_min_peek(hp)) != NULL);
187 TEST_MSG("expected %i elements remaining in the heap", left - i);
188
190 TEST_MSG("failed extracting %i", i);
191 }
192
193 TEST_CHECK((ret = fr_minmax_heap_num_elements(hp)) == 0);
194 TEST_MSG("%i elements remaining", ret);
195
196 talloc_free(hp);
197}
198
199/*
200 * minmax heaps can do anything heaps can do, so let's make sure we have
201 * a (proper!) superset of the heap tests.
202 */
203
204static void minmax_heap_test_skip_0(void)
205{
207}
208
209static void minmax_heap_test_skip_2(void)
210{
212}
213
215{
217}
218
219#define BURN_IN_OPS (10000000)
220
221static void minmax_heap_burn_in(void)
222{
223 fr_minmax_heap_t *hp = NULL;
224 minmax_heap_thing *array = NULL;
225 fr_fast_rand_t rand_ctx;
226 int insert_count = 0;
227
228 rand_ctx.a = fr_rand();
229 rand_ctx.b = fr_rand();
230
231 array = calloc(BURN_IN_OPS, sizeof(minmax_heap_thing));
232 for (unsigned int i = 0; i < BURN_IN_OPS; i++) array[i].data = fr_fast_rand(&rand_ctx) % 65537;
233
235 TEST_CHECK(hp != NULL);
236
237 for (unsigned int i = 0; i < BURN_IN_OPS; i++) {
238 minmax_heap_thing *ret_thing = NULL;
239 int ret_insert = -1;
240
241 if (fr_minmax_heap_num_elements(hp) == 0) {
242 insert:
243 TEST_CHECK((ret_insert = fr_minmax_heap_insert(hp, &array[insert_count])) >= 0);
244 insert_count++;
245 } else {
246 switch (fr_fast_rand(&rand_ctx) % 5) {
247 case 0: /* insert */
248 goto insert;
249
250 case 1: /* min pop */
251 ret_thing = fr_minmax_heap_min_pop(hp);
252 TEST_CHECK(ret_thing != NULL);
253 break;
254 case 2: /* min peek */
255 ret_thing = fr_minmax_heap_min_peek(hp);
256 TEST_CHECK(ret_thing != NULL);
257 break;
258 case 3: /* max pop */
259 ret_thing = fr_minmax_heap_max_pop(hp);
260 TEST_CHECK(ret_thing != NULL);
261 break;
262 case 4: /* max peek */
263 ret_thing = fr_minmax_heap_max_peek(hp);
264 TEST_CHECK(ret_thing != NULL);
265 break;
266 }
267 }
268 }
269
270 talloc_free(hp);
271 free(array);
272}
273
274#define MINMAX_HEAP_CYCLE_SIZE (1600000)
275
276static void minmax_heap_test_order(void)
277{
279 int i;
280 minmax_heap_thing *array;
281 minmax_heap_thing *thing, *prev = NULL;
282 unsigned int data;
283 unsigned int count;
284 int ret;
285 fr_fast_rand_t rand_ctx;
286
287 rand_ctx.a = fr_rand();
288 rand_ctx.b = fr_rand();
289
291 TEST_CHECK(hp != NULL);
292
293 array = talloc_zero_array(hp, minmax_heap_thing, MINMAX_HEAP_TEST_SIZE);
294
295 /*
296 * Initialise random values
297 */
298 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) array[i].data = fr_fast_rand(&rand_ctx) % 65537;
299
300 TEST_CASE("insertions for min");
301 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) {
302 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
303 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
304
305 TEST_CHECK(minmax_heap_contains(hp, &array[i]));
306 TEST_MSG("element %i inserted but not in heap", i);
307 }
308
309 TEST_CASE("min ordering");
310
311 count = 0;
312 data = 0;
313 prev = NULL;
314 while ((thing = fr_minmax_heap_min_pop(hp))) {
315 TEST_CHECK(thing->data >= data);
316 TEST_MSG("Expected data >= %u, got %u", data, thing->data);
317 if (thing->data >= data) data = thing->data;
318 TEST_CHECK(thing != prev);
319 prev = thing;
320 count++;
321 }
322
324
325 TEST_CASE("insertions for max");
326 for (i = 0; i < MINMAX_HEAP_TEST_SIZE; i++) {
327 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
328 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
329
330 TEST_CHECK(minmax_heap_contains(hp, &array[i]));
331 TEST_MSG("element %i inserted but not in heap", i);
332 }
333
334 TEST_CASE("max ordering");
335
336 count = 0;
337 data = UINT_MAX;
338 prev = NULL;
339 while ((thing = fr_minmax_heap_max_pop(hp))) {
340 TEST_CHECK(thing->data <= data);
341 TEST_MSG("Expected data >= %u, got %u", data, thing->data);
342 if (thing->data <= data) data = thing->data;
343 TEST_CHECK(thing != prev);
344 prev = thing;
345 count++;
346 }
347
349
350 talloc_free(hp);
351}
352
353static CC_HINT(noinline) minmax_heap_thing *array_pop(minmax_heap_thing **array, unsigned int count)
354{
355 minmax_heap_thing *low = NULL;
356 unsigned int idx = 0;
357
358 for (unsigned int j = 0; j < count; j++) {
359 if (!array[j]) continue;
360
361 if (!low || (minmax_heap_cmp(array[j], low) < 0)) {
362 idx = j;
363 low = array[j];
364 }
365 }
366 if (low) array[idx] = NULL;
367
368 return low;
369}
370
371/** Benchmarks for minmax heaps vs heaps when used as queues
372 *
373 */
374static void queue_cmp(unsigned int count)
375{
376 fr_minmax_heap_t *minmax;
377 fr_heap_t *hp;
378
379 minmax_heap_thing *values;
380
381 unsigned int i;
382
383 values = talloc_array(NULL, minmax_heap_thing, count);
384
385 /*
386 * Check times for minmax heap alloc, insert, pop
387 */
388 {
389 fr_time_t start_alloc, end_alloc, start_insert, end_insert, start_pop, end_pop, end_pop_first = fr_time_wrap(0);
390
391 populate_values(values, count);
392
393 start_alloc = fr_time();
395 end_alloc = fr_time();
396 TEST_CHECK(minmax != NULL);
397
398 start_insert = fr_time();
399 for (i = 0; i < count; i++) fr_minmax_heap_insert(minmax, &values[i]);
400 end_insert = fr_time();
401
402 start_pop = fr_time();
403 for (i = 0; i < count; i++) {
404 TEST_CHECK(fr_minmax_heap_min_pop(minmax) != NULL);
405 if (i == 0) end_pop_first = fr_time();
406
407 TEST_MSG("expected %u elements remaining in the minmax heap", count - i);
408 TEST_MSG("failed extracting %u", i);
409 }
410 end_pop = fr_time();
411
412 TEST_MSG_ALWAYS("\nminmax heap size: %u\n", count);
413 TEST_MSG_ALWAYS("alloc: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_alloc, start_alloc)));
414 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_insert, start_insert)));
415 TEST_MSG_ALWAYS("pop-first: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop_first, start_pop)));
416 TEST_MSG_ALWAYS("pop: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop, start_pop)));
417 talloc_free(minmax);
418 }
419
420 /*
421 * Check times for heap alloc, insert, pop
422 */
423 {
424 fr_time_t start_alloc, end_alloc, start_insert, end_insert, start_pop, end_pop, end_pop_first = fr_time_min();
425
426 populate_values(values, count);
427
428 start_alloc = fr_time();
430 end_alloc = fr_time();
431 TEST_CHECK(hp != NULL);
432
433 start_insert = fr_time();
434 for (i = 0; i < count; i++) fr_heap_insert(&hp, &values[i]);
435 end_insert = fr_time();
436
437 start_pop = fr_time();
438 for (i = 0; i < count; i++) {
439 TEST_CHECK(fr_heap_pop(&hp) != NULL);
440 if (i == 0) end_pop_first = fr_time();
441
442 TEST_MSG("expected %u elements remaining in the heap", count - i);
443 TEST_MSG("failed extracting %u", i);
444 }
445 end_pop = fr_time();
446
447 TEST_MSG_ALWAYS("\nheap size: %u\n", count);
448 TEST_MSG_ALWAYS("alloc: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_alloc, start_alloc)));
449 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_insert, start_insert)));
450 TEST_MSG_ALWAYS("pop-first: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop_first, start_pop)));
451 TEST_MSG_ALWAYS("pop: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop, start_pop)));
452
453 talloc_free(hp);
454 }
455
456 /*
457 * Array
458 */
459 {
460 minmax_heap_thing **array;
461 fr_time_t start_alloc, end_alloc, start_insert, end_insert, start_pop, end_pop, end_pop_first;
462
463 populate_values(values, count);
464 end_pop_first = fr_time_min();
465
466 start_alloc = fr_time();
467 array = talloc_array(NULL, minmax_heap_thing *, count);
468 end_alloc = fr_time();
469
470 start_insert = fr_time();
471 for (i = 0; i < count; i++) array[i] = &values[i];
472 end_insert = fr_time();
473
474 start_pop = fr_time();
475 for (i = 0; i < count; i++) {
476 TEST_CHECK(array_pop(array, count) != NULL);
477 if (i == 0) end_pop_first = fr_time();
478 }
479 end_pop = fr_time();
480
481 TEST_MSG_ALWAYS("\narray size: %u\n", count);
482 TEST_MSG_ALWAYS("alloc: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_alloc, start_alloc)));
483 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_insert, start_insert)));
484 TEST_MSG_ALWAYS("pop-first: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop_first, start_pop)));
485 TEST_MSG_ALWAYS("pop: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end_pop, start_pop)));
486
487 talloc_free(array);
488 }
489
490 talloc_free(values);
491}
492
493static void queue_cmp_10(void)
494{
495 queue_cmp(10);
496}
497
498static void queue_cmp_50(void)
499{
500 queue_cmp(50);
501}
502
503static void queue_cmp_100(void)
504{
505 queue_cmp(100);
506}
507
508static void queue_cmp_1000(void)
509{
510 queue_cmp(1000);
511}
512
513static void minmax_heap_cycle(void)
514{
516 int i;
517 minmax_heap_thing *array;
518 int to_remove;
519 int inserted, removed;
520 int ret;
521 fr_time_t start_insert, start_remove, start_swap, end;
522 fr_fast_rand_t rand_ctx;
523
524 rand_ctx.a = fr_rand();
525 rand_ctx.b = fr_rand();
526
528 TEST_CHECK(hp != NULL);
529
530 array = calloc(MINMAX_HEAP_CYCLE_SIZE, sizeof(minmax_heap_thing));
531
532 /*
533 * Initialise random values
534 */
535 for (i = 0; i < MINMAX_HEAP_CYCLE_SIZE; i++) array[i].data = fr_fast_rand(&rand_ctx) % 65537;
536
537 start_insert = fr_time();
538 TEST_CASE("insertions");
539 for (i = 0; i < MINMAX_HEAP_CYCLE_SIZE; i++) {
540 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
541 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
542 }
544
545 TEST_CASE("pop");
546
547 /*
548 * Remove a random number of elements from the heap
549 */
550 to_remove = fr_minmax_heap_num_elements(hp) / 2;
551 start_remove = fr_time();
552 for (i = 0; i < to_remove; i++) {
554
555 TEST_CHECK((t = fr_minmax_heap_min_peek(hp)) != NULL);
556 TEST_MSG("expected %i elements remaining in the heap", to_remove - i);
557
559 TEST_MSG("failed extracting %i - %s", i, fr_strerror());
560 }
561
562 /*
563 * Now swap the inserted and removed set creating churn
564 */
565 start_swap = fr_time();
566 inserted = 0;
567 removed = 0;
568
569 for (i = 0; i < MINMAX_HEAP_CYCLE_SIZE; i++) {
570 if (!fr_minmax_heap_entry_inserted(array[i].idx)) {
571 TEST_CHECK((ret = fr_minmax_heap_insert(hp, &array[i])) >= 0);
572 TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
573 inserted++;
574 } else {
575 TEST_CHECK((ret = fr_minmax_heap_extract(hp, &array[i])) >= 0);
576 TEST_MSG("element %i removal failed, returned %i - %s", i, ret, fr_strerror());
577 removed++;
578 }
579 }
580
581 TEST_CHECK(removed == (MINMAX_HEAP_CYCLE_SIZE - to_remove));
582 TEST_MSG("expected %i", MINMAX_HEAP_CYCLE_SIZE - to_remove);
583 TEST_MSG("got %i", removed);
584
585 TEST_CHECK(inserted == to_remove);
586 TEST_MSG("expected %i", to_remove);
587 TEST_MSG("got %i", inserted);
588
589 end = fr_time();
590
591 TEST_MSG_ALWAYS("\ncycle size: %d\n", MINMAX_HEAP_CYCLE_SIZE);
592 TEST_MSG_ALWAYS("insert: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(start_remove, start_insert)));
593 TEST_MSG_ALWAYS("extract: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(start_swap, start_remove)));
594 TEST_MSG_ALWAYS("swap: %"PRId64" μs\n", fr_time_delta_to_usec(fr_time_sub(end, start_swap)));
595
596 talloc_free(hp);
597 free(array);
598}
599
600static void minmax_heap_iter(void)
601{
605 unsigned int total;
606
608 TEST_CHECK(hp != NULL);
609
610 populate_values(values, NUM_ELEMENTS(values));
611
612 for (unsigned int i = 0; i < NUM_ELEMENTS(values); i++) fr_minmax_heap_insert(hp, &values[i]);
613
614 data = fr_minmax_heap_iter_init(hp, &iter);
615
616 for (unsigned int i = 0; i < NUM_ELEMENTS(values); i++, data = fr_minmax_heap_iter_next(hp, &iter)) {
617 TEST_CHECK(data != NULL);
618 TEST_CHECK(!data->visited);
619 TEST_CHECK(data->idx > 0);
620 data->visited = true;
621 }
622
623 TEST_CHECK(data == NULL);
624
625 total = 0;
627 total += item->data;
628 }}
629 TEST_CHECK(total = 190);
630
632}
633
635 /*
636 * Basic tests
637 */
638 { "minmax_heap_test_basic", minmax_heap_test_basic },
639 { "minmax_heap_test_skip_0", minmax_heap_test_skip_0 },
640 { "minmax_heap_test_skip_2", minmax_heap_test_skip_2 },
641 { "minmax_heap_test_skip_10", minmax_heap_test_skip_10 },
642 { "minmax_heap_test_order", minmax_heap_test_order },
643 { "minmax_heap_burn_in", minmax_heap_burn_in },
644 { "minmax_heap_cycle", minmax_heap_cycle },
645 { "minmax_heap_iter", minmax_heap_iter },
646 { "queue_cmp_10", queue_cmp_10 },
647 { "queue_cmp_50", queue_cmp_50 },
648 { "queue_cmp_100", queue_cmp_100 },
649 { "queue_cmp_1000", queue_cmp_1000 },
650 { NULL }
651};
652
#define TEST_MSG_ALWAYS(...)
Definition acutest.h:222
#define TEST_CHECK(cond)
Definition acutest.h:85
#define TEST_CASE(name)
Definition acutest.h:184
#define TEST_MSG(...)
Definition acutest.h:215
#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:337
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:322
#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)
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
Functions for a minmax heap.
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:163
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition state_test.c:8
#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:554
static fr_slen_t data
Definition value.h:1265