array allocator for dbengine page descriptors (#13312)
* array allocator for dbengine page descriptors * full implementation of array allocator with cleanup * faster deallocations * eliminate entierely the need for loops during free * addressed comments * lower the min number of elements to 10
Costa Tsaousis committed
Jul 8, 2022 at 00:09 UTC
a6da6beb71f31ed5e89d9ed7a5a7d3242cdd8d8e
14 files changed
+461
-9
CMakeLists.txt
+2
@@ -370,6 +370,8 @@ set(LIBNETDATA_FILES
370
libnetdata/adaptive_resortable_list/adaptive_resortable_list.h
371
libnetdata/config/appconfig.c
372
libnetdata/config/appconfig.h
373
+ libnetdata/arrayalloc/arrayalloc.c
374
+ libnetdata/arrayalloc/arrayalloc.h
375
libnetdata/avl/avl.c
376
libnetdata/avl/avl.h
377
libnetdata/buffer/buffer.c
Makefile.am
+2
@@ -136,6 +136,8 @@ LIBNETDATA_FILES = \
136
libnetdata/adaptive_resortable_list/adaptive_resortable_list.h \
137
libnetdata/config/appconfig.c \
138
libnetdata/config/appconfig.h \
139
+ libnetdata/arrayalloc/arrayalloc.c \
140
+ libnetdata/arrayalloc/arrayalloc.h \
141
libnetdata/avl/avl.c \
142
libnetdata/avl/avl.h \
143
libnetdata/buffer/buffer.c \
configure.ac
+1
@@ -1724,6 +1724,7 @@ AC_CONFIG_FILES([
1724
libnetdata/Makefile
1725
libnetdata/tests/Makefile
1726
libnetdata/adaptive_resortable_list/Makefile
1727
+ libnetdata/arrayalloc/Makefile
1728
libnetdata/avl/Makefile
1729
libnetdata/buffer/Makefile
1730
libnetdata/clocks/Makefile
database/engine/pagecache.c
+47
-3
@@ -3,6 +3,50 @@
3
4
#include "rrdengine.h"
5
6
+ARAL page_descr_aral = {
7
+ .element_size = sizeof(struct rrdeng_page_descr),
8
+ .elements = 20000,
9
+ .filename = "page_descriptors",
10
+ .cache_dir = &netdata_configured_cache_dir,
11
+ .use_mmap = false,
12
+ .internal.initialized = false
13
+};
14
+
15
+void rrdeng_page_descr_aral_go_singlethreaded(void) {
16
+ page_descr_aral.internal.lockless = true;
17
+}
18
+void rrdeng_page_descr_aral_go_multithreaded(void) {
19
+ page_descr_aral.internal.lockless = false;
20
+}
21
+
22
+struct rrdeng_page_descr *rrdeng_page_descr_mallocz(void) {
23
+ struct rrdeng_page_descr *descr;
24
+ descr = arrayalloc_mallocz(&page_descr_aral);
25
+ return descr;
26
+}
27
+
28
+void rrdeng_page_descr_freez(struct rrdeng_page_descr *descr) {
29
+ arrayalloc_freez(&page_descr_aral, descr);
30
+}
31
+
32
+void rrdeng_page_descr_use_malloc(void) {
33
+ if(page_descr_aral.internal.initialized)
34
+ error("DBENGINE: cannot change ARAL allocation policy after it has been initialized.");
35
+ else
36
+ page_descr_aral.use_mmap = false;
37
+}
38
+
39
+void rrdeng_page_descr_use_mmap(void) {
40
+ if(page_descr_aral.internal.initialized)
41
+ error("DBENGINE: cannot change ARAL allocation policy after it has been initialized.");
42
+ else
43
+ page_descr_aral.use_mmap = true;
44
+}
45
+
46
+bool rrdeng_page_descr_is_mmap(void) {
47
+ return page_descr_aral.use_mmap;
48
+}
49
+
50
/* Forward declarations */
51
static int pg_cache_try_evict_one_page_unsafe(struct rrdengine_instance *ctx);
52
@@ -81,7 +125,7 @@ struct rrdeng_page_descr *pg_cache_create_descr(void)
125
{
126
struct rrdeng_page_descr *descr;
127
84
- descr = mallocz(sizeof(*descr));
128
+ descr = rrdeng_page_descr_mallocz();
129
descr->page_length = 0;
130
descr->start_time = INVALID_TIME;
131
descr->end_time = INVALID_TIME;
@@ -494,7 +538,7 @@ uint8_t pg_cache_punch_hole(struct rrdengine_instance *ctx, struct rrdeng_page_d
538
(void)sleep_usec(1000); /* 1 msec */
539
}
540
destroy:
497
- freez(descr);
541
+ rrdeng_page_descr_freez(descr);
542
pg_cache_update_metric_times(page_index);
543
544
return can_delete_metric;
@@ -1312,7 +1356,7 @@ void free_page_cache(struct rrdengine_instance *ctx)
1356
else
1357
metric_single_point_pages++;
1358
1315
- freez(descr);
1359
+ rrdeng_page_descr_freez(descr);
1360
pages_bytes += sizeof(*descr);
1361
pages_number++;
1362
database/engine/pagecache.h
+8
@@ -195,6 +195,14 @@ extern unsigned long pg_cache_hard_limit(struct rrdengine_instance *ctx);
195
extern unsigned long pg_cache_soft_limit(struct rrdengine_instance *ctx);
196
extern unsigned long pg_cache_committed_hard_limit(struct rrdengine_instance *ctx);
197
198
+extern void rrdeng_page_descr_aral_go_singlethreaded(void);
199
+extern void rrdeng_page_descr_aral_go_multithreaded(void);
200
+extern void rrdeng_page_descr_use_malloc(void);
201
+extern void rrdeng_page_descr_use_mmap(void);
202
+extern bool rrdeng_page_descr_is_mmap(void);
203
+extern struct rrdeng_page_descr *rrdeng_page_descr_mallocz(void);
204
+extern void rrdeng_page_descr_freez(struct rrdeng_page_descr *descr);
205
+
206
static inline void
207
pg_cache_atomic_get_pg_info(struct rrdeng_page_descr *descr, usec_t *end_timep, uint32_t *page_lengthp)
208
{
database/engine/rrdengineapi.c
+1
-1
@@ -211,7 +211,7 @@ void rrdeng_store_metric_flush_current_page(STORAGE_COLLECT_HANDLE *collection_h
211
} else {
212
dbengine_page_free(descr->pg_cache_descr->page);
213
rrdeng_destroy_pg_cache_descr(ctx, descr->pg_cache_descr);
214
- freez(descr);
214
+ rrdeng_page_descr_freez(descr);
215
}
216
handle->descr = NULL;
217
}
database/rrdhost.c
+9
@@ -768,6 +768,11 @@ int rrd_init(char *hostname, struct rrdhost_system_info *system_info) {
768
default_rrdeng_page_fetch_retries = 1;
769
config_set_number(CONFIG_SECTION_DB, "dbengine page fetch retries", default_rrdeng_page_fetch_retries);
770
}
771
+
772
+ if(config_get_boolean(CONFIG_SECTION_DB, "dbengine page descriptors in file mapped memory", rrdeng_page_descr_is_mmap()) == CONFIG_BOOLEAN_YES)
773
+ rrdeng_page_descr_use_mmap();
774
+ else
775
+ rrdeng_page_descr_use_malloc();
776
#endif
777
778
rrdset_free_obsolete_time = config_get_number(CONFIG_SECTION_DB, "cleanup obsolete charts after secs", rrdset_free_obsolete_time);
@@ -825,6 +830,8 @@ int rrd_init(char *hostname, struct rrdhost_system_info *system_info) {
830
}
831
832
#ifdef ENABLE_DBENGINE
833
+ rrdeng_page_descr_aral_go_singlethreaded();
834
+
835
int created_tiers = 0;
836
char dbenginepath[FILENAME_MAX + 1];
837
char dbengineconfig[200 + 1];
@@ -905,6 +912,8 @@ int rrd_init(char *hostname, struct rrdhost_system_info *system_info) {
912
rrd_unlock();
913
fatal("DBENGINE: Failed to be initialized.");
914
}
915
+
916
+ rrdeng_page_descr_aral_go_multithreaded();
917
#else
918
storage_tiers = config_get_number(CONFIG_SECTION_DB, "storage tiers", 1);
919
if(storage_tiers != 1) {
libnetdata/Makefile.am
+1
@@ -5,6 +5,7 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
5
6
SUBDIRS = \
7
adaptive_resortable_list \
8
+ arrayalloc \
9
avl \
10
buffer \
11
clocks \
libnetdata/arrayalloc/Makefile.am
new
+8
@@ -0,0 +1,8 @@
1
+# SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+AUTOMAKE_OPTIONS = subdir-objects
4
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
5
+
6
+dist_noinst_DATA = \
7
+ README.md \
8
+ $(NULL)
libnetdata/arrayalloc/README.md
new
+7
@@ -0,0 +1,7 @@
1
+<!--
2
+title: "Array Allocator"
3
+custom_edit_url: https://github.com/netdata/netdata/edit/master/libnetdata/arrayalloc/README.md
4
+-->
5
+
6
+# Array Allocator
7
+
libnetdata/arrayalloc/arrayalloc.c
new
+334
@@ -0,0 +1,334 @@
1
+#include "../libnetdata.h"
2
+#include "arrayalloc.h"
3
+#include "daemon/common.h"
4
+
5
+// max file size
6
+#define ARAL_MAX_PAGE_SIZE_MMAP (1*1024*1024*1024)
7
+
8
+// max malloc size
9
+#define ARAL_MAX_PAGE_SIZE_MALLOC (10*1024*1024)
10
+
11
+typedef struct arrayalloc_free {
12
+ size_t size;
13
+ struct arrayalloc_page *page;
14
+ struct arrayalloc_free *next;
15
+} ARAL_FREE;
16
+
17
+typedef struct arrayalloc_page {
18
+ const char *filename;
19
+ size_t size; // the total size of the page
20
+ size_t used_elements; // the total number of used elements on this page
21
+ uint8_t *data;
22
+ ARAL_FREE *free_list;
23
+ struct arrayalloc_page *prev; // the prev page on the list
24
+ struct arrayalloc_page *next; // the next page on the list
25
+} ARAL_PAGE;
26
+
27
+#define ARAL_NATURAL_ALIGNMENT (sizeof(uintptr_t) * 2)
28
+static inline size_t natural_alignment(size_t size, size_t alignment) {
29
+ if(unlikely(size % alignment))
30
+ size = size + alignment - (size % alignment);
31
+
32
+ return size;
33
+}
34
+
35
+static void arrayalloc_init(ARAL *ar) {
36
+ static netdata_mutex_t mutex = NETDATA_MUTEX_INITIALIZER;
37
+ netdata_mutex_lock(&mutex);
38
+
39
+ if(!ar->internal.initialized) {
40
+ netdata_mutex_init(&ar->internal.mutex);
41
+
42
+ long int page_size = sysconf(_SC_PAGE_SIZE);
43
+ if (unlikely(page_size == -1))
44
+ ar->internal.natural_page_size = 4096;
45
+ else
46
+ ar->internal.natural_page_size = page_size;
47
+
48
+ // we need to add a page pointer after the element
49
+ // so, first align the element size to the pointer size
50
+ ar->internal.element_size = natural_alignment(ar->element_size, sizeof(uintptr_t));
51
+
52
+ // then add the size of a pointer to it
53
+ ar->internal.element_size = ar->internal.element_size + sizeof(uintptr_t);
54
+
55
+ // make sure it is at least what we need for an ARAL_FREE slot
56
+ if (ar->internal.element_size < sizeof(ARAL_FREE))
57
+ ar->internal.element_size = sizeof(ARAL_FREE);
58
+
59
+ // and finally align it to the natural alignment
60
+ ar->internal.element_size = natural_alignment(ar->element_size, ARAL_NATURAL_ALIGNMENT);
61
+
62
+ // this is where we should write the pointer
63
+ ar->internal.page_ptr_offset = ar->internal.element_size - sizeof(uintptr_t);
64
+
65
+ if(ar->element_size + sizeof(uintptr_t) > ar->internal.element_size)
66
+ fatal("ARRAYALLOC: failed to calculate properly page_ptr_offset: element size %zu, sizeof(uintptr_t) %zu, natural alignment %zu, final element size %zu, page_ptr_offset %zu",
67
+ ar->element_size, sizeof(uintptr_t), ARAL_NATURAL_ALIGNMENT, ar->internal.element_size, ar->internal.page_ptr_offset);
68
+
69
+ //info("ARRAYALLOC: element size %zu, sizeof(uintptr_t) %zu, natural alignment %zu, final element size %zu, page_ptr_offset %zu",
70
+ // ar->element_size, sizeof(uintptr_t), ARAL_NATURAL_ALIGNMENT, ar->internal.element_size, ar->internal.page_ptr_offset);
71
+
72
+ if (ar->elements < 10)
73
+ ar->elements = 10;
74
+
75
+ ar->internal.mmap = (ar->use_mmap && ar->cache_dir && *ar->cache_dir) ? true : false;
76
+ ar->internal.max_alloc_size = ar->internal.mmap ? ARAL_MAX_PAGE_SIZE_MMAP : ARAL_MAX_PAGE_SIZE_MALLOC;
77
+
78
+ if(ar->internal.max_alloc_size % ar->internal.natural_page_size)
79
+ ar->internal.max_alloc_size += ar->internal.natural_page_size - (ar->internal.max_alloc_size % ar->internal.natural_page_size) ;
80
+
81
+ if(ar->internal.max_alloc_size % ar->internal.element_size)
82
+ ar->internal.max_alloc_size -= ar->internal.max_alloc_size % ar->internal.element_size;
83
+
84
+ ar->internal.first_page = NULL;
85
+ ar->internal.last_page = NULL;
86
+ ar->internal.allocation_multiplier = 1;
87
+ ar->internal.file_number = 0;
88
+
89
+ if(ar->internal.mmap) {
90
+ char filename[FILENAME_MAX + 1];
91
+ snprintfz(filename, FILENAME_MAX, "%s/array_alloc.mmap", *ar->cache_dir);
92
+ int r = mkdir(filename, 0775);
93
+ if (r != 0 && errno != EEXIST)
94
+ fatal("Cannot create directory '%s'", filename);
95
+ }
96
+
97
+ ar->internal.initialized = true;
98
+ }
99
+
100
+ netdata_mutex_unlock(&mutex);
101
+}
102
+
103
+#ifdef NETDATA_INTERNAL_CHECKS
104
+static inline void arrayalloc_free_checks(ARAL *ar, ARAL_FREE *fr) {
105
+ if(fr->size < ar->internal.element_size)
106
+ fatal("ARRAYALLOC: free item of size %zu, less than the expected element size %zu", fr->size, ar->internal.element_size);
107
+
108
+ if(fr->size % ar->internal.element_size)
109
+ fatal("ARRAYALLOC: free item of size %zu is not multiple to element size %zu", fr->size, ar->internal.element_size);
110
+}
111
+#else
112
+#define arrayalloc_free_checks(ar, fr) debug_dummy()
113
+#endif
114
+
115
+static inline void unlink_page(ARAL *ar, ARAL_PAGE *page) {
116
+ if(unlikely(!page)) return;
117
+
118
+ if(page->next)
119
+ page->next->prev = page->prev;
120
+
121
+ if(page->prev)
122
+ page->prev->next = page->next;
123
+
124
+ if(page == ar->internal.first_page)
125
+ ar->internal.first_page = page->next;
126
+
127
+ if(page == ar->internal.last_page)
128
+ ar->internal.last_page = page->prev;
129
+}
130
+
131
+static inline void link_page_first(ARAL *ar, ARAL_PAGE *page) {
132
+ page->prev = NULL;
133
+ page->next = ar->internal.first_page;
134
+ if(page->next) page->next->prev = page;
135
+
136
+ ar->internal.first_page = page;
137
+
138
+ if(!ar->internal.last_page)
139
+ ar->internal.last_page = page;
140
+}
141
+
142
+static inline void link_page_last(ARAL *ar, ARAL_PAGE *page) {
143
+ page->next = NULL;
144
+ page->prev = ar->internal.last_page;
145
+ if(page->prev) page->prev->next = page;
146
+
147
+ ar->internal.last_page = page;
148
+
149
+ if(!ar->internal.first_page)
150
+ ar->internal.first_page = page;
151
+}
152
+
153
+static inline ARAL_PAGE *find_page_with_allocation(ARAL *ar, void *ptr) {
154
+ size_t seeking = (size_t)ptr;
155
+ ARAL_PAGE *page;
156
+
157
+ for(page = ar->internal.first_page; page ; page = page->next) {
158
+ if(unlikely(seeking >= (size_t)page->data && seeking < (size_t)page->data + page->size))
159
+ break;
160
+ }
161
+
162
+ return page;
163
+}
164
+
165
+static void arrayalloc_increase(ARAL *ar) {
166
+ if(unlikely(!ar->internal.initialized))
167
+ arrayalloc_init(ar);
168
+
169
+ ARAL_PAGE *page = callocz(1, sizeof(ARAL_PAGE));
170
+ page->size = ar->elements * ar->internal.element_size * ar->internal.allocation_multiplier;
171
+ if(page->size > ar->internal.max_alloc_size)
172
+ page->size = ar->internal.max_alloc_size;
173
+ else
174
+ ar->internal.allocation_multiplier *= 2;
175
+
176
+ if(ar->internal.mmap) {
177
+ ar->internal.file_number++;
178
+ char filename[FILENAME_MAX + 1];
179
+ snprintfz(filename, FILENAME_MAX, "%s/array_alloc.mmap/%s.%zu", *ar->cache_dir, ar->filename, ar->internal.file_number);
180
+ page->filename = strdupz(filename);
181
+ page->data = netdata_mmap(page->filename, page->size, MAP_SHARED, 0);
182
+ if (unlikely(!page->data))
183
+ fatal("Cannot allocate arrayalloc buffer of size %zu on filename '%s'", page->size, page->filename);
184
+ }
185
+ else
186
+ page->data = mallocz(page->size);
187
+
188
+ // link the free space to its page
189
+ ARAL_FREE *fr = (ARAL_FREE *)page->data;
190
+ fr->size = page->size;
191
+ fr->page = page;
192
+ fr->next = NULL;
193
+ page->free_list = fr;
194
+
195
+ // link the new page at the front of the list of pages
196
+ link_page_first(ar, page);
197
+
198
+ arrayalloc_free_checks(ar, fr);
199
+}
200
+
201
+static void arrayalloc_lock(ARAL *ar) {
202
+ if(!ar->internal.lockless)
203
+ netdata_mutex_lock(&ar->internal.mutex);
204
+}
205
+
206
+static void arrayalloc_unlock(ARAL *ar) {
207
+ if(!ar->internal.lockless)
208
+ netdata_mutex_unlock(&ar->internal.mutex);
209
+}
210
+
211
+ARAL *arrayalloc_create(size_t element_size, size_t elements, const char *filename, char **cache_dir) {
212
+ ARAL *ar = callocz(1, sizeof(ARAL));
213
+ ar->element_size = element_size;
214
+ ar->elements = elements;
215
+ ar->filename = filename;
216
+ ar->cache_dir = cache_dir;
217
+ return ar;
218
+}
219
+
220
+void *arrayalloc_mallocz(ARAL *ar) {
221
+ arrayalloc_lock(ar);
222
+
223
+ if(unlikely(!ar->internal.first_page || !ar->internal.first_page->free_list))
224
+ arrayalloc_increase(ar);
225
+
226
+ ARAL_PAGE *page = ar->internal.first_page;
227
+ ARAL_FREE *fr = page->free_list;
228
+
229
+ if(unlikely(!fr))
230
+ fatal("ARRAYALLOC: free item cannot be NULL.");
231
+
232
+ if(unlikely(fr->size < ar->internal.element_size))
233
+ fatal("ARRAYALLOC: free item size %zu is smaller than %zu", fr->size, ar->internal.element_size);
234
+
235
+ if(fr->size - ar->internal.element_size <= ar->internal.element_size) {
236
+ // we are done with this page
237
+ page->free_list = NULL;
238
+
239
+ if(page != ar->internal.last_page) {
240
+ unlink_page(ar, page);
241
+ link_page_last(ar, page);
242
+ }
243
+ }
244
+ else {
245
+ uint8_t *data = (uint8_t *)fr;
246
+ ARAL_FREE *fr2 = (ARAL_FREE *)&data[ar->internal.element_size];
247
+ fr2->page = fr->page;
248
+ fr2->size = fr->size - ar->internal.element_size;
249
+ fr2->next = fr->next;
250
+ page->free_list = fr2;
251
+
252
+ arrayalloc_free_checks(ar, fr2);
253
+ }
254
+
255
+ fr->page->used_elements++;
256
+
257
+ // put the page pointer after the element
258
+ uint8_t *data = (uint8_t *)fr;
259
+ ARAL_PAGE **page_ptr = (ARAL_PAGE **)&data[ar->internal.page_ptr_offset];
260
+ *page_ptr = page;
261
+
262
+ arrayalloc_unlock(ar);
263
+ return (void *)fr;
264
+}
265
+
266
+void arrayalloc_freez(ARAL *ar, void *ptr) {
267
+ if(!ptr) return;
268
+ arrayalloc_lock(ar);
269
+
270
+ // get the page pointer
271
+ ARAL_PAGE *page;
272
+ {
273
+ uint8_t *data = (uint8_t *)ptr;
274
+ ARAL_PAGE **page_ptr = (ARAL_PAGE **)&data[ar->internal.page_ptr_offset];
275
+ page = *page_ptr;
276
+
277
+#ifdef NETDATA_INTERNAL_CHECKS
278
+ // make it NULL so that we will fail on double free
279
+ // do not enable this on production, because the MMAP file
280
+ // will need to be saved again!
281
+ *page_ptr = NULL;
282
+#endif
283
+ }
284
+
285
+#ifdef NETDATA_INTERNAL_CHECKS
286
+ {
287
+ // find the page ptr belongs
288
+ ARAL_PAGE *page2 = find_page_with_allocation(ar, ptr);
289
+
290
+ if(unlikely(page != page2))
291
+ fatal("ARRAYALLOC: page pointers do not match!");
292
+
293
+ if (unlikely(!page2))
294
+ fatal("ARRAYALLOC: free of pointer %p is not in arrayalloc address space.", ptr);
295
+ }
296
+#endif
297
+
298
+ if(unlikely(!page))
299
+ fatal("ARRAYALLOC: possible corruption or double free of pointer %p", ptr);
300
+
301
+ if (unlikely(!page->used_elements))
302
+ fatal("ARRAYALLOC: free of pointer %p is inside a page without any active allocations.", ptr);
303
+
304
+ page->used_elements--;
305
+
306
+ // make this element available
307
+ ARAL_FREE *fr = (ARAL_FREE *)ptr;
308
+ fr->page = page;
309
+ fr->size = ar->internal.element_size;
310
+ fr->next = page->free_list;
311
+ page->free_list = fr;
312
+
313
+ // if the page is empty, release it
314
+ if(!page->used_elements) {
315
+ unlink_page(ar, page);
316
+
317
+ // free it
318
+ if(ar->internal.mmap) {
319
+ munmap(page->data, page->size);
320
+ unlink(page->filename);
321
+ freez((void *)page->filename);
322
+ }
323
+ else
324
+ freez(page->data);
325
+
326
+ freez(page);
327
+ }
328
+ else if(page != ar->internal.first_page) {
329
+ unlink_page(ar, page);
330
+ link_page_first(ar, page);
331
+ }
332
+
333
+ arrayalloc_unlock(ar);
334
+}
libnetdata/arrayalloc/arrayalloc.h
new
+35
@@ -0,0 +1,35 @@
1
+
2
+#ifndef ARRAYALLOC_H
3
+#define ARRAYALLOC_H 1
4
+
5
+#include "../libnetdata.h"
6
+
7
+typedef struct arrayalloc {
8
+ size_t element_size;
9
+ size_t elements;
10
+ const char *filename;
11
+ char **cache_dir;
12
+ bool use_mmap;
13
+
14
+ // private members - do not touch
15
+ struct {
16
+ bool mmap;
17
+ bool lockless;
18
+ bool initialized;
19
+ size_t element_size;
20
+ size_t page_ptr_offset;
21
+ size_t file_number;
22
+ size_t natural_page_size;
23
+ size_t allocation_multiplier;
24
+ size_t max_alloc_size;
25
+ netdata_mutex_t mutex;
26
+ struct arrayalloc_page *first_page;
27
+ struct arrayalloc_page *last_page;
28
+ } internal;
29
+} ARAL;
30
+
31
+extern ARAL *arrayalloc_create(size_t element_size, size_t elements, const char *filename, char **cache_dir);
32
+extern void *arrayalloc_mallocz(ARAL *ar);
33
+extern void arrayalloc_freez(ARAL *ar, void *ptr);
34
+
35
+#endif // ARRAYALLOC_H
libnetdata/libnetdata.h
+1
@@ -345,6 +345,7 @@ extern char *netdata_configured_host_prefix;
345
#include "json/json.h"
346
#include "health/health.h"
347
#include "string/utf8.h"
348
+#include "arrayalloc/arrayalloc.h"
349
#include "onewayalloc/onewayalloc.h"
350
#include "worker_utilization/worker_utilization.h"
351
libnetdata/onewayalloc/onewayalloc.c
+5
-5
@@ -1,9 +1,7 @@
1
#include "onewayalloc.h"
2
3
-static size_t OWA_NATURAL_PAGE_SIZE = 0;
4
-
3
// https://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html
6
-#define OWA_NATURAL_ALIGNMENT (sizeof(void *) * 2)
4
+#define OWA_NATURAL_ALIGNMENT (sizeof(uintptr_t) * 2)
5
6
typedef struct owa_page {
7
size_t stats_pages;
@@ -30,6 +28,8 @@ static inline size_t natural_alignment(size_t size) {
28
// any number of times, for any amount of memory.
29
30
static OWA_PAGE *onewayalloc_create_internal(OWA_PAGE *head, size_t size_hint) {
31
+ static size_t OWA_NATURAL_PAGE_SIZE = 0;
32
+
33
if(unlikely(!OWA_NATURAL_PAGE_SIZE)) {
34
long int page_size = sysconf(_SC_PAGE_SIZE);
35
if (unlikely(page_size == -1))
@@ -82,11 +82,11 @@ static OWA_PAGE *onewayalloc_create_internal(OWA_PAGE *head, size_t size_hint) {
82
head->stats_pages++;
83
head->stats_pages_size += size;
84
85
- return (ONEWAYALLOC *)page;
85
+ return page;
86
}
87
88
ONEWAYALLOC *onewayalloc_create(size_t size_hint) {
89
- return onewayalloc_create_internal(NULL, size_hint);
89
+ return (ONEWAYALLOC *)onewayalloc_create_internal(NULL, size_hint);
90
}
91
92
void *onewayalloc_mallocz(ONEWAYALLOC *owa, size_t size) {