mirror of
https://git.freebsd.org/ports.git
synced 2025-04-28 01:26:39 -04:00
116 lines
2.6 KiB
Text
116 lines
2.6 KiB
Text
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
|
|
|