mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-01-23 17:31:55 +00:00
Allocate the normalization buckets on stack
Even though allocating from tmp_linpool is quite cheap, it isn't cheap when the block is larger than a page, which is the case here. Instead, we now allocate just the result which typically fits in a page, avoiding a necessity of a malloc().
This commit is contained in:
parent
4f7899e3cb
commit
ffa57a4303
@ -967,8 +967,8 @@ ea_list_size(ea_list *o)
|
|||||||
* and creates the final structure useful for storage or fast searching.
|
* and creates the final structure useful for storage or fast searching.
|
||||||
* The method is a bucket sort.
|
* The method is a bucket sort.
|
||||||
*
|
*
|
||||||
* Returns the final ea_list with some excess memory at the end,
|
* Returns the final ea_list allocated from the tmp_linpool.
|
||||||
* allocated from the tmp_linpool. The adata is linked from the original places.
|
* The adata is linked from the original places.
|
||||||
*/
|
*/
|
||||||
ea_list *
|
ea_list *
|
||||||
ea_normalize(ea_list *e, u32 upto)
|
ea_normalize(ea_list *e, u32 upto)
|
||||||
@ -976,21 +976,17 @@ ea_normalize(ea_list *e, u32 upto)
|
|||||||
/* We expect some work to be actually needed. */
|
/* We expect some work to be actually needed. */
|
||||||
ASSERT_DIE(!BIT32_TEST(&upto, e->stored));
|
ASSERT_DIE(!BIT32_TEST(&upto, e->stored));
|
||||||
|
|
||||||
/* Allocate the output */
|
/* Allocate the buckets locally */
|
||||||
ea_list *out = tmp_allocz(ea_class_max * sizeof(eattr) + sizeof(ea_list));
|
eattr *buckets = allocz(ea_class_max * sizeof(eattr));
|
||||||
*out = (ea_list) {
|
|
||||||
.flags = EALF_SORTED,
|
|
||||||
};
|
|
||||||
|
|
||||||
uint min_id = ~0, max_id = 0;
|
uint min_id = ~0, max_id = 0;
|
||||||
|
|
||||||
eattr *buckets = out->attrs;
|
ea_list *next = NULL;
|
||||||
|
|
||||||
/* Walk the attribute lists, one after another. */
|
/* Walk the attribute lists, one after another. */
|
||||||
for (; e; e = e->next)
|
for (; e; e = e->next)
|
||||||
{
|
{
|
||||||
if (!out->next && BIT32_TEST(&upto, e->stored))
|
if (!next && BIT32_TEST(&upto, e->stored))
|
||||||
out->next = e;
|
next = e;
|
||||||
|
|
||||||
for (int i = 0; i < e->count; i++)
|
for (int i = 0; i < e->count; i++)
|
||||||
{
|
{
|
||||||
@ -1000,7 +996,7 @@ ea_normalize(ea_list *e, u32 upto)
|
|||||||
if (id < min_id)
|
if (id < min_id)
|
||||||
min_id = id;
|
min_id = id;
|
||||||
|
|
||||||
if (out->next)
|
if (next)
|
||||||
{
|
{
|
||||||
/* Underlay: check whether the value is duplicate */
|
/* Underlay: check whether the value is duplicate */
|
||||||
if (buckets[id].id && buckets[id].fresh)
|
if (buckets[id].id && buckets[id].fresh)
|
||||||
@ -1026,6 +1022,18 @@ ea_normalize(ea_list *e, u32 upto)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find out how big the output actually is. */
|
||||||
|
uint len = 0;
|
||||||
|
for (uint id = min_id; id <= max_id; id++)
|
||||||
|
if (buckets[id].id && !(buckets[id].undef && buckets[id].fresh))
|
||||||
|
len++;
|
||||||
|
|
||||||
|
ea_list *out = tmp_alloc(sizeof(ea_list) + len * sizeof(eattr));
|
||||||
|
*out = (ea_list) {
|
||||||
|
.flags = EALF_SORTED,
|
||||||
|
.next = next,
|
||||||
|
};
|
||||||
|
|
||||||
/* And now we just walk the list from beginning to end and collect
|
/* And now we just walk the list from beginning to end and collect
|
||||||
* everything to the beginning of the list.
|
* everything to the beginning of the list.
|
||||||
* Walking just that part which is inhabited for sure. */
|
* Walking just that part which is inhabited for sure. */
|
||||||
@ -1044,9 +1052,12 @@ ea_normalize(ea_list *e, u32 upto)
|
|||||||
|
|
||||||
/* Move the attribute to the beginning */
|
/* Move the attribute to the beginning */
|
||||||
ASSERT_DIE(out->count < id);
|
ASSERT_DIE(out->count < id);
|
||||||
buckets[out->count++] = buckets[id];
|
ASSERT_DIE(out->count < len);
|
||||||
|
out->attrs[out->count++] = buckets[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT_DIE(out->count == len);
|
||||||
|
|
||||||
/* We want to bisect only if the list is long enough */
|
/* We want to bisect only if the list is long enough */
|
||||||
if (out->count > 5)
|
if (out->count > 5)
|
||||||
out->flags |= EALF_BISECT;
|
out->flags |= EALF_BISECT;
|
||||||
|
Loading…
Reference in New Issue
Block a user