* element count, assume expanding past
* that size is going to be the uncommon
* case.
+ *
+ * We seem to need two headers here otherwise
+ * we overflow the pool, and we get a
+ * significant slowdown in allocation performance.
*/
if (init) {
- hp = talloc_zero_pooled_object(ctx, fr_heap_t, 1, sizeof(void *) * init);
+ hp = talloc_pooled_object(ctx, fr_heap_t, 2, sizeof(void *) * init);
} else {
init = INITIAL_CAPACITY;
- hp = talloc_zero(ctx, fr_heap_t);
+ hp = talloc(ctx, fr_heap_t);
}
if (unlikely(!hp)) return NULL;
- hp->size = init;
- hp->p = talloc_array(hp, void *, hp->size);
+ *hp = (fr_heap_t){
+ .size = init,
+ .p = talloc_array(hp, void *, init),
+ .type = type,
+ .cmp = cmp,
+ .offset = offset
+ };
+
if (unlikely(!hp->p)) {
talloc_free(hp);
return NULL;
* into the heap.
*/
hp->p[0] = (void *)UINTPTR_MAX;
- hp->type = type;
- hp->cmp = cmp;
- hp->offset = offset;
return hp;
}
* If we pre-allocated the array of elements
* we'd end up wasting that memory as soon as
* we needed to expand the array.
+ *
+ * Pre-allocating three chunks appears to be
+ * the optimum.
*/
- lst = talloc_zero_pooled_object(ctx, fr_lst_t, 2, (INITIAL_STACK_CAPACITY * sizeof(fr_lst_index_t)));
+ lst = talloc_zero_pooled_object(ctx, fr_lst_t, 3, (INITIAL_STACK_CAPACITY * sizeof(fr_lst_index_t)));
if (unlikely(!lst)) return NULL;
lst->capacity = INITIAL_CAPACITY;
end_lst_pop = fr_time();
TEST_MSG_ALWAYS("\nlst size: %zu\n", NUM_ELEMENTS(values));
- TEST_MSG_ALWAYS("alloc: %"PRIu64" ns\n", end_lst_alloc - start_lst_alloc);
- TEST_MSG_ALWAYS("insert: %"PRIu64" ns\n", end_lst_insert - start_lst_insert);
- TEST_MSG_ALWAYS("pop: %"PRIu64" ns\n", end_lst_pop - start_lst_pop);
+ TEST_MSG_ALWAYS("alloc: %"PRIu64" μs\n", (end_lst_alloc - start_lst_alloc) / 1000);
+ TEST_MSG_ALWAYS("insert: %"PRIu64" μs\n", (end_lst_insert - start_lst_insert) / 1000);
+ TEST_MSG_ALWAYS("pop: %"PRIu64" μs\n", (end_lst_pop - start_lst_pop) / 1000);
talloc_free(lst);
populate_values(values, NUM_ELEMENTS(values));
start_heap_alloc = fr_time();
- heap = fr_heap_alloc(NULL, lst_cmp, lst_thing, idx, 0);
+ heap = fr_heap_alloc(NULL, lst_cmp, lst_thing, idx, NUM_ELEMENTS(values));
end_heap_alloc = fr_time();
TEST_CHECK(heap != NULL);
end_heap_pop = fr_time();
TEST_MSG_ALWAYS("\nheap size: %zu\n", NUM_ELEMENTS(values));
- TEST_MSG_ALWAYS("alloc: %"PRIu64" ns\n", end_heap_alloc - start_heap_alloc);
- TEST_MSG_ALWAYS("insert: %"PRIu64" ns\n", end_heap_insert - start_heap_insert);
- TEST_MSG_ALWAYS("pop: %"PRIu64" ns\n", end_heap_pop - start_heap_pop);
+ TEST_MSG_ALWAYS("alloc: %"PRIu64" μs\n", (end_heap_alloc - start_heap_alloc) / 1000);
+ TEST_MSG_ALWAYS("insert: %"PRIu64" μs\n", (end_heap_insert - start_heap_insert) / 1000);
+ TEST_MSG_ALWAYS("pop: %"PRIu64" μs\n", (end_heap_pop - start_heap_pop) / 1000);
talloc_free(heap);
}