0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-02 23:21:54 +00:00

Stonehenge: multi-slab allocator

To mid-term allocate and free lots of small blocks in a fast pace,
mb_alloc is too slow and causes heap bloating. We can already allocate
blocks from slabs, and if we allow for a little bit of inefficiency,
we can just use multiple slabs with stepped sizes.

This technique is already used in ea_list allocation which is gonna be
converted to Stonehenge.
This commit is contained in:
Maria Matejka 2024-12-24 12:18:39 +01:00
parent f7639a9faf
commit f6ef8b5b58
2 changed files with 76 additions and 0 deletions

View File

@ -139,6 +139,20 @@ void *sl_allocz(slab *);
void sl_free(void *);
void sl_delete(slab *);
/* A whole stonehenge of slabs */
typedef struct stonehenge stonehenge;
typedef struct sth_block {
void *block;
bool large;
} sth_block;
stonehenge *sth_new(pool *);
sth_block sth_alloc(stonehenge *, uint size);
sth_block sth_allocz(stonehenge *, uint size);
void sth_free(sth_block);
void sth_delete(stonehenge *);
/*
* Low-level memory allocation functions, please don't use
* outside resource manager and possibly sysdep code.

View File

@ -469,4 +469,66 @@ slab_lookup(resource *r, unsigned long a)
return NULL;
}
static const uint stonehenge_sizes[] = { 56, 112, 168, 288, 448, 800, 1344 };
struct stonehenge {
pool *p;
slab *s[ARRAY_SIZE(stonehenge_sizes)];
};
sth_block
sth_alloc(stonehenge *sth, uint size)
{
for (uint i=0; i<ARRAY_SIZE(stonehenge_sizes); i++)
if (size <= stonehenge_sizes[i])
{
if (!sth->s[i])
sth->s[i] = sl_new(sth->p, stonehenge_sizes[i]);
return (sth_block) { .block = sl_alloc(sth->s[i]), };
}
return (sth_block) {
.block = mb_alloc(sth->p, size),
.large = 1,
};
}
sth_block
sth_allocz(stonehenge *sth, uint size)
{
sth_block b = sth_alloc(sth, size);
bzero(b.block, size);
return b;
}
void
sth_free(sth_block b)
{
if (b.large)
mb_free(b.block);
else
sl_free(b.block);
}
stonehenge *
sth_new(pool *pp)
{
stonehenge tmps = {
.p = rp_new(pp, pp->domain, "Stonehenge"),
};
stonehenge *s = sth_alloc(&tmps, sizeof(stonehenge)).block;
*s = tmps;
return s;
}
void sth_delete(stonehenge *s)
{
pool *p = s->p;
sth_free((sth_block) { s });
rp_free(p);
}
#endif