summaryrefslogtreecommitdiff
path: root/net/bird3/files/patch-10-stonehenge
blob: a640442dae8d228b79815b2e9e92d36f1539277c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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