From f6ef8b5b58c674dd270b40aa57d20d2d638c48e9 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Tue, 24 Dec 2024 12:18:39 +0100 Subject: [PATCH] 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. --- lib/resource.h | 14 ++++++++++++ lib/slab.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/lib/resource.h b/lib/resource.h index 48bf1f9b..12b78851 100644 --- a/lib/resource.h +++ b/lib/resource.h @@ -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. diff --git a/lib/slab.c b/lib/slab.c index ca971f9f..d68bfef1 100644 --- a/lib/slab.c +++ b/lib/slab.c @@ -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; is[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