diff options
Diffstat (limited to 'net/bird3/files/patch-10-stonehenge')
-rw-r--r-- | net/bird3/files/patch-10-stonehenge | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/net/bird3/files/patch-10-stonehenge b/net/bird3/files/patch-10-stonehenge new file mode 100644 index 000000000000..a640442dae8d --- /dev/null +++ b/net/bird3/files/patch-10-stonehenge @@ -0,0 +1,116 @@ +From f6ef8b5b58c674dd270b40aa57d20d2d638c48e9 Mon Sep 17 00:00:00 2001 +From: Maria Matejka <mq@ucw.cz> +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 48bf1f9ba..12b788510 100644 +--- lib/resource.h ++++ 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 ca971f9fb..d68bfef1e 100644 +--- lib/slab.c ++++ 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; 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 +-- +GitLab + |