@cryptotaxi247 / netdata-1 / commits / 21a545ae8

added mmap count charts (#19384)

* added mmap count charts * buffers should not be extended * read max_map_count once per minute

Costa Tsaousis committed Jan 12, 2025 at 19:06 UTC 21a545ae84b052fcaef74877d1793c145c96fc23
5 files changed +311 -234
CMakeLists.txt
+1
@@ -1152,6 +1152,7 @@ set(DAEMON_FILES
1152 src/daemon/config/netdata-conf-cloud.h
1153 src/daemon/config/netdata-conf-profile.c
1154 src/daemon/config/netdata-conf-profile.h
1155 + src/daemon/pulse/pulse-daemon-memory-system.c
1156 )
1157
1158 set(H2O_FILES
src/daemon/pulse/pulse-daemon-memory-system.c new
+300
@@ -0,0 +1,300 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#define PULSE_INTERNALS 1
4 +#include "pulse-daemon-memory.h"
5 +#include "streaming/stream-replication-sender.h"
6 +
7 +#if defined(HAVE_C_MALLOC_INFO) || defined(HAVE_C_MALLINFO2)
8 +#include <malloc.h>
9 +#endif
10 +
11 +#ifdef HAVE_C_MALLOC_INFO
12 +// Helper function to find the last occurrence of a substring in a string
13 +static char *find_last(const char *haystack, const char *needle, size_t *found) {
14 + *found = 0;
15 +
16 + char *last = NULL;
17 + char *current = strstr(haystack, needle);
18 + while (current) {
19 + (*found)++;
20 + last = current;
21 + current = strstr(current + 1, needle);
22 + }
23 + return last;
24 +}
25 +
26 +static bool parse_malloc_info(size_t *arenas, size_t *allocated_arena, size_t *unused_fast, size_t *unused_rest, size_t *allocated_mmap) {
27 + int found = 0;
28 +
29 + *arenas = 0;
30 + *allocated_arena = 0;
31 + *unused_fast = 0;
32 + *unused_rest = 0;
33 + *allocated_mmap = 0;
34 +
35 + // Buffer for malloc_info XML
36 + char *buffer = NULL;
37 + size_t size = 0;
38 + FILE *meminfo = open_memstream(&buffer, &size);
39 + if (!meminfo)
40 + goto cleanup;
41 +
42 + char *t = malloc(1024);
43 +
44 + // Generate malloc_info XML
45 + if(malloc_info(0, meminfo) != 0)
46 + goto cleanup;
47 +
48 + fflush(meminfo);
49 + fclose(meminfo);
50 + meminfo = NULL;
51 +
52 + free(t);
53 +
54 + if(!size || !buffer)
55 + goto cleanup;
56 +
57 + // make sure it is terminated
58 + buffer[size - 1] = '\0';
59 +
60 + // Find the last </heap>
61 + char *last_heap_end = find_last(buffer, "</heap>", arenas);
62 + if (!last_heap_end)
63 + goto cleanup;
64 +
65 + // Move past the last </heap>
66 + char *summary_section = last_heap_end + strlen("</heap>");
67 +
68 + // Parse the summary section using strstr
69 + const char *fast_key = "<total type=\"fast\"";
70 + const char *rest_key = "<total type=\"rest\"";
71 + const char *mmap_key = "<total type=\"mmap\"";
72 + const char *system_key = "<system type=\"current\"";
73 + char *size_pos;
74 +
75 + char *fast_pos = strstr(summary_section, fast_key);
76 + if(!fast_pos || !(size_pos = strstr(fast_pos, "size=\"")))
77 + goto cleanup;
78 +
79 + *unused_fast = strtoull(size_pos + 6, NULL, 10);
80 + found++;
81 +
82 + char *rest_pos = strstr(summary_section, rest_key);
83 + if (!rest_pos || !(size_pos = strstr(rest_pos, "size=\"")))
84 + goto cleanup;
85 +
86 + *unused_rest = strtoull(size_pos + 6, NULL, 10);
87 + found++;
88 +
89 + char *mmap_pos = strstr(summary_section, mmap_key);
90 + if (!mmap_pos || !(size_pos = strstr(mmap_pos, "size=\"")))
91 + goto cleanup;
92 +
93 + *allocated_mmap = strtoull(size_pos + 6, NULL, 10);
94 + found++;
95 +
96 + char *system_pos = strstr(summary_section, system_key);
97 + if (!system_pos || !(size_pos = strstr(system_pos, "size=\"")))
98 + goto cleanup;
99 +
100 + *allocated_arena = strtoull(size_pos + 6, NULL, 10);
101 + found++;
102 +
103 +cleanup:
104 + if(meminfo) fclose(meminfo);
105 + if(buffer) free(buffer);
106 + return found == 4;
107 +}
108 +#endif // HAVE_C_MALLOC_INFO
109 +
110 +void pulse_daemon_memory_system_do(bool extended) {
111 +
112 +#ifdef HAVE_C_MALLOC_INFO
113 + size_t glibc_arenas, glibc_allocated_arenas, glibc_unused_fast, glibc_unused_rest, glibc_allocated_mmap;
114 + if(extended && parse_malloc_info(&glibc_arenas, &glibc_allocated_arenas, &glibc_unused_fast, &glibc_unused_rest, &glibc_allocated_mmap)) {
115 + if (glibc_arenas) {
116 + static RRDSET *st_arenas = NULL;
117 + static RRDDIM *rd_arenas = NULL;
118 +
119 + if (unlikely(!st_arenas)) {
120 + st_arenas = rrdset_create_localhost(
121 + "netdata",
122 + "glibc_arenas",
123 + NULL,
124 + "Memory Usage",
125 + NULL,
126 + "Glibc Memory Arenas",
127 + "arenas",
128 + "netdata",
129 + "pulse",
130 + 130120,
131 + localhost->rrd_update_every,
132 + RRDSET_TYPE_LINE);
133 +
134 + rd_arenas = rrddim_add(st_arenas, "arenas", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
135 + }
136 +
137 + rrddim_set_by_pointer(st_arenas, rd_arenas, (collected_number)glibc_arenas);
138 + rrdset_done(st_arenas);
139 + }
140 +
141 + if (glibc_allocated_arenas || glibc_allocated_mmap) {
142 + static RRDSET *st_malloc = NULL;
143 + static RRDDIM *rd_unused_fast = NULL;
144 + static RRDDIM *rd_unused_rest = NULL;
145 + static RRDDIM *rd_used_arena = NULL;
146 + static RRDDIM *rd_used_mmap = NULL;
147 +
148 + if (unlikely(!st_malloc)) {
149 + st_malloc = rrdset_create_localhost(
150 + "netdata",
151 + "glibc_malloc_info",
152 + NULL,
153 + "Memory Usage",
154 + NULL,
155 + "Glibc Malloc Info",
156 + "bytes",
157 + "netdata",
158 + "pulse",
159 + 130121,
160 + localhost->rrd_update_every,
161 + RRDSET_TYPE_STACKED);
162 +
163 + rd_unused_fast = rrddim_add(st_malloc, "unused fast", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
164 + rd_unused_rest = rrddim_add(st_malloc, "unused rest", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
165 + rd_used_arena = rrddim_add(st_malloc, "used arena", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
166 + rd_used_mmap = rrddim_add(st_malloc, "used mmap", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
167 + }
168 +
169 + size_t unused = glibc_unused_fast + glibc_unused_rest;
170 + size_t used_arena = (glibc_allocated_arenas > unused) ? glibc_allocated_arenas - unused : 0;
171 +
172 + rrddim_set_by_pointer(st_malloc, rd_unused_fast, (collected_number)glibc_unused_fast);
173 + rrddim_set_by_pointer(st_malloc, rd_unused_rest, (collected_number)glibc_unused_rest);
174 + rrddim_set_by_pointer(st_malloc, rd_used_arena, (collected_number)used_arena);
175 + rrddim_set_by_pointer(st_malloc, rd_used_mmap, (collected_number)glibc_allocated_mmap);
176 + rrdset_done(st_malloc);
177 + }
178 + }
179 +#endif
180 +
181 + size_t glibc_mmaps = 0;
182 +
183 +#ifdef HAVE_C_MALLINFO2
184 + struct mallinfo2 mi = mallinfo2();
185 + glibc_mmaps = mi.hblks;
186 + if(extended && (mi.hblkhd || mi.fordblks)) {
187 + static RRDSET *st_mallinfo = NULL;
188 + static RRDDIM *rd_used_mmap = NULL;
189 + static RRDDIM *rd_used_arena = NULL;
190 + static RRDDIM *rd_unused_fragments = NULL;
191 + static RRDDIM *rd_unused_releasable = NULL;
192 +
193 + if (unlikely(!st_mallinfo)) {
194 + st_mallinfo = rrdset_create_localhost(
195 + "netdata",
196 + "glibc_mallinfo2",
197 + NULL,
198 + "Memory Usage",
199 + NULL,
200 + "Glibc Mallinfo2 Memory Distribution",
201 + "bytes",
202 + "netdata",
203 + "pulse",
204 + 130130,
205 + localhost->rrd_update_every,
206 + RRDSET_TYPE_STACKED);
207 +
208 + rd_unused_releasable = rrddim_add(st_mallinfo, "unused releasable", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
209 + rd_unused_fragments = rrddim_add(st_mallinfo, "unused fragments", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
210 + rd_used_arena = rrddim_add(st_mallinfo, "used arena", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
211 + rd_used_mmap = rrddim_add(st_mallinfo, "used mmap", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
212 + }
213 +
214 + // size_t total = mi.uordblks;
215 + size_t used_mmap = mi.hblkhd;
216 + size_t used_arena = (mi.arena > mi.fordblks) ? mi.arena - mi.fordblks : 0;
217 +
218 + size_t unused_total = mi.fordblks;
219 + size_t unused_releasable = mi.keepcost;
220 + // size_t unused_fast = mi.fsmblks;
221 + size_t unused_fragments = (unused_total > unused_releasable) ? unused_total - unused_releasable : 0;
222 +
223 + rrddim_set_by_pointer(st_mallinfo, rd_unused_releasable, (collected_number)unused_releasable);
224 + rrddim_set_by_pointer(st_mallinfo, rd_unused_fragments, (collected_number)unused_fragments);
225 + rrddim_set_by_pointer(st_mallinfo, rd_used_arena, (collected_number)used_arena);
226 + rrddim_set_by_pointer(st_mallinfo, rd_used_mmap, (collected_number)used_mmap);
227 +
228 + rrdset_done(st_mallinfo);
229 + }
230 +#endif // HAVE_C_MALLINFO2
231 +
232 + size_t netdata_mmaps = __atomic_load_n(&netdata_mmap_count, __ATOMIC_RELAXED);
233 + size_t total_mmaps = netdata_mmaps + glibc_mmaps;
234 + {
235 + static RRDSET *st_maps = NULL;
236 + static RRDDIM *rd_netdata = NULL;
237 + static RRDDIM *rd_glibc = NULL;
238 +
239 + if (unlikely(!st_maps)) {
240 + st_maps = rrdset_create_localhost(
241 + "netdata",
242 + "memory_maps",
243 + NULL,
244 + "Memory Usage",
245 + NULL,
246 + "Netdata Memory Maps",
247 + "maps",
248 + "netdata",
249 + "pulse",
250 + 130105,
251 + localhost->rrd_update_every,
252 + RRDSET_TYPE_LINE);
253 +
254 + rd_netdata = rrddim_add(st_maps, "netdata", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
255 + rd_glibc = rrddim_add(st_maps, "glibc", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
256 + }
257 +
258 + rrddim_set_by_pointer(st_maps, rd_glibc, (collected_number)netdata_mmaps);
259 + rrddim_set_by_pointer(st_maps, rd_netdata, (collected_number)glibc_mmaps);
260 +
261 + rrdset_done(st_maps);
262 + }
263 +
264 + static unsigned long long max_map_count = 0;
265 + static usec_t last_read_ut = 0;
266 + usec_t now_ut = now_monotonic_usec();
267 + if(now_ut - last_read_ut >= 60 * USEC_PER_SEC) {
268 + // read this file once per minute
269 + read_single_number_file("/proc/sys/vm/max_map_count", &max_map_count);
270 + last_read_ut = now_ut;
271 + }
272 +
273 + if (max_map_count && total_mmaps) {
274 + static RRDSET *st_maps_percent = NULL;
275 + static RRDDIM *rd_used = NULL;
276 +
277 + if (unlikely(!st_maps_percent)) {
278 + st_maps_percent = rrdset_create_localhost(
279 + "netdata",
280 + "memory_maps_limit",
281 + NULL,
282 + "Memory Usage",
283 + NULL,
284 + "Netdata Memory Maps Limit",
285 + "%",
286 + "netdata",
287 + "pulse",
288 + 130106,
289 + localhost->rrd_update_every,
290 + RRDSET_TYPE_AREA);
291 +
292 + rd_used = rrddim_add(st_maps_percent, "used", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
293 + }
294 +
295 + double percent = (double)total_mmaps * 100.0 / (double)max_map_count;
296 +
297 + rrddim_set_by_pointer(st_maps_percent, rd_used, (collected_number)round(percent * 1000.0));
298 + rrdset_done(st_maps_percent);
299 + }
300 +}
src/daemon/pulse/pulse-daemon-memory.c
+2 -233
@@ -9,117 +9,7 @@
9
10 struct netdata_buffers_statistics netdata_buffers_statistics = { 0 };
11
12 -#if defined(HAVE_C_MALLOC_INFO) || defined(HAVE_C_MALLINFO2)
13 -#include <malloc.h>
14 -#endif
15 -
16 -#ifdef HAVE_C_MALLOC_INFO
17 -// Helper function to find the last occurrence of a substring in a string
18 -static char *find_last(const char *haystack, const char *needle, size_t *found) {
19 - *found = 0;
20 -
21 - char *last = NULL;
22 - char *current = strstr(haystack, needle);
23 - while (current) {
24 - (*found)++;
25 - last = current;
26 - current = strstr(current + 1, needle);
27 - }
28 - return last;
29 -}
30 -
31 -static bool parse_malloc_info(size_t *arenas, size_t *allocated_memory, size_t *used_fast, size_t *used_rest, size_t *used_mmap, size_t *unused_memory) {
32 - int found = 0;
33 -
34 - *arenas = 0;
35 - *allocated_memory = 0;
36 - *used_fast = 0;
37 - *used_rest = 0;
38 - *used_mmap = 0;
39 - *unused_memory = 0;
40 -
41 - // Buffer for malloc_info XML
42 - char *buffer = NULL;
43 - size_t size = 0;
44 - FILE *meminfo = open_memstream(&buffer, &size);
45 - if (!meminfo)
46 - goto cleanup;
47 -
48 - char *t = malloc(1024);
49 -
50 - // Generate malloc_info XML
51 - if(malloc_info(0, meminfo) != 0)
52 - goto cleanup;
53 -
54 - fflush(meminfo);
55 - fclose(meminfo);
56 - meminfo = NULL;
57 -
58 - free(t);
59 -
60 - if(!size || !buffer)
61 - goto cleanup;
62 -
63 - // make sure it is terminated
64 - buffer[size - 1] = '\0';
65 -
66 - // Find the last </heap>
67 - char *last_heap_end = find_last(buffer, "</heap>", arenas);
68 - if (!last_heap_end)
69 - goto cleanup;
70 -
71 - // Move past the last </heap>
72 - char *summary_section = last_heap_end + strlen("</heap>");
73 -
74 - // Parse the summary section using strstr
75 - const char *fast_key = "<total type=\"fast\"";
76 - const char *rest_key = "<total type=\"rest\"";
77 - const char *mmap_key = "<total type=\"mmap\"";
78 - const char *system_key = "<system type=\"current\"";
79 - char *size_pos;
80 -
81 - // Extract Used Fast
82 - char *fast_pos = strstr(summary_section, fast_key);
83 - if(!fast_pos || !(size_pos = strstr(fast_pos, "size=\"")))
84 - goto cleanup;
85 -
86 - *used_fast = strtoull(size_pos + 6, NULL, 10);
87 - found++;
88 -
89 - // Extract Used Rest
90 - char *rest_pos = strstr(summary_section, rest_key);
91 - if (!rest_pos || !(size_pos = strstr(rest_pos, "size=\"")))
92 - goto cleanup;
93 -
94 - *used_rest = strtoull(size_pos + 6, NULL, 10);
95 - found++;
96 -
97 - // Extract Used Mmap
98 - char *mmap_pos = strstr(summary_section, mmap_key);
99 - if (!mmap_pos || !(size_pos = strstr(mmap_pos, "size=\"")))
100 - goto cleanup;
101 -
102 - *used_mmap = strtoull(size_pos + 6, NULL, 10);
103 - found++;
104 -
105 - // Extract Allocated Memory
106 - char *system_pos = strstr(summary_section, system_key);
107 - if (!system_pos || !(size_pos = strstr(system_pos, "size=\"")))
108 - goto cleanup;
109 -
110 - *allocated_memory = strtoull(size_pos + 6, NULL, 10);
111 - found++;
112 -
113 - // Calculate Unused Memory
114 - *unused_memory = *allocated_memory > (*used_fast + *used_rest + *used_mmap) ?
115 - *allocated_memory - (*used_fast + *used_rest + *used_mmap) : 0;
116 -
117 -cleanup:
118 - if(meminfo) fclose(meminfo);
119 - if(buffer) free(buffer);
120 - return found == 4;
121 -}
122 -#endif // HAVE_C_MALLOC_INFO
12 +void pulse_daemon_memory_system_do(bool extended);
13
14 void pulse_daemon_memory_do(bool extended) {
15 {
@@ -323,11 +213,6 @@ void pulse_daemon_memory_do(bool extended) {
213
214 // ----------------------------------------------------------------------------------------------------------------
215
326 - if(!extended)
327 - return;
328 -
329 - // ----------------------------------------------------------------------------------------------------------------
330 -
216 {
217 static RRDSET *st_memory_buffers = NULL;
218 static RRDDIM *rd_queries = NULL;
@@ -397,121 +282,5 @@ void pulse_daemon_memory_do(bool extended) {
282
283 // ----------------------------------------------------------------------------------------------------------------
284
400 -#ifdef HAVE_C_MALLOC_INFO
401 - size_t glibc_arenas, glibc_allocated_memory, glibc_used_fast, glibc_used_rest, glibc_used_mmap, glibc_unused_memory;
402 - if(parse_malloc_info(&glibc_arenas, &glibc_allocated_memory, &glibc_used_fast, &glibc_used_rest, &glibc_used_mmap, &glibc_unused_memory)) {
403 - if (glibc_arenas) {
404 - static RRDSET *st_arenas = NULL;
405 - static RRDDIM *rd_arenas = NULL;
406 -
407 - if (unlikely(!st_arenas)) {
408 - st_arenas = rrdset_create_localhost(
409 - "netdata",
410 - "glibc_arenas",
411 - NULL,
412 - "Memory Usage",
413 - NULL,
414 - "Glibc Memory Arenas",
415 - "arenas",
416 - "netdata",
417 - "pulse",
418 - 130104,
419 - localhost->rrd_update_every,
420 - RRDSET_TYPE_LINE);
421 -
422 - rd_arenas = rrddim_add(st_arenas, "arenas", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
423 - }
424 -
425 - // the sum of all these needs to be above at the total buffers calculation
426 - rrddim_set_by_pointer(st_arenas, rd_arenas, (collected_number)glibc_arenas);
427 - rrdset_done(st_arenas);
428 - }
429 -
430 - if (glibc_allocated_memory > 0 && glibc_used_fast + glibc_used_rest + glibc_used_mmap + glibc_unused_memory > 0) {
431 - static RRDSET *st_malloc = NULL;
432 - static RRDDIM *rd_unused = NULL;
433 - static RRDDIM *rd_fast = NULL;
434 - static RRDDIM *rd_rest = NULL;
435 - static RRDDIM *rd_mmap = NULL;
436 -
437 - if (unlikely(!st_malloc)) {
438 - st_malloc = rrdset_create_localhost(
439 - "netdata",
440 - "glibc_malloc_info",
441 - NULL,
442 - "Memory Usage",
443 - NULL,
444 - "Glibc Malloc Info",
445 - "bytes",
446 - "netdata",
447 - "pulse",
448 - 130105,
449 - localhost->rrd_update_every,
450 - RRDSET_TYPE_STACKED);
451 -
452 - rd_unused = rrddim_add(st_malloc, "unused", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
453 - rd_fast = rrddim_add(st_malloc, "fast", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
454 - rd_rest = rrddim_add(st_malloc, "rest", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
455 - rd_mmap = rrddim_add(st_malloc, "mmap", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
456 - }
457 -
458 - // the sum of all these needs to be above at the total buffers calculation
459 - rrddim_set_by_pointer(st_malloc, rd_unused, (collected_number)glibc_unused_memory);
460 - rrddim_set_by_pointer(st_malloc, rd_fast, (collected_number)glibc_used_fast);
461 - rrddim_set_by_pointer(st_malloc, rd_rest, (collected_number)glibc_used_rest);
462 - rrddim_set_by_pointer(st_malloc, rd_mmap, (collected_number)glibc_used_mmap);
463 - rrdset_done(st_malloc);
464 - }
465 - }
466 -#endif
467 -
468 -#ifdef HAVE_C_MALLINFO2
469 - {
470 - static RRDSET *st_mallinfo = NULL;
471 - static RRDDIM *rd_used_mmap = NULL;
472 - static RRDDIM *rd_used_arena = NULL;
473 - static RRDDIM *rd_unused_fragments = NULL;
474 - static RRDDIM *rd_unused_releasable = NULL;
475 -
476 - if (unlikely(!st_mallinfo)) {
477 - st_mallinfo = rrdset_create_localhost(
478 - "netdata",
479 - "glibc_mallinfo2",
480 - NULL,
481 - "Memory Usage",
482 - NULL,
483 - "Glibc Mallinfo2 Memory Distribution",
484 - "bytes",
485 - "netdata",
486 - "pulse",
487 - 130106,
488 - localhost->rrd_update_every,
489 - RRDSET_TYPE_STACKED);
490 -
491 - rd_unused_releasable = rrddim_add(st_mallinfo, "unused releasable", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
492 - rd_unused_fragments = rrddim_add(st_mallinfo, "unused fragments", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
493 - rd_used_arena = rrddim_add(st_mallinfo, "used arena", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
494 - rd_used_mmap = rrddim_add(st_mallinfo, "used mmap", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
495 - }
496 -
497 - struct mallinfo2 mi = mallinfo2();
498 -
499 - // size_t total = mi.uordblks;
500 - size_t used_mmap = mi.hblkhd;
501 - size_t used_arena = (mi.arena > mi.fordblks) ? mi.arena - mi.fordblks : 0;
502 -
503 - size_t unused_total = mi.fordblks;
504 - size_t unused_releasable = mi.keepcost;
505 - // size_t unused_fast = mi.fsmblks;
506 - size_t unused_fragments = (unused_total > unused_releasable) ? unused_total - unused_releasable : 0;
507 -
508 - rrddim_set_by_pointer(st_mallinfo, rd_unused_releasable, (collected_number)unused_releasable);
509 - rrddim_set_by_pointer(st_mallinfo, rd_unused_fragments, (collected_number)unused_fragments);
510 - rrddim_set_by_pointer(st_mallinfo, rd_used_arena, (collected_number)used_arena);
511 - rrddim_set_by_pointer(st_mallinfo, rd_used_mmap, (collected_number)used_mmap);
512 -
513 - rrdset_done(st_mallinfo);
514 - }
515 -#endif // HAVE_C_MALLINFO2
516 -
285 + pulse_daemon_memory_system_do(extended);
286 }
src/libnetdata/libnetdata.c
+7 -1
@@ -599,6 +599,8 @@ inline int madvise_mergeable(void *mem __maybe_unused, size_t len __maybe_unused
599 #endif
600 }
601
602 +size_t netdata_mmap_count = 0;
603 +
604 void *netdata_mmap(const char *filename, size_t size, int flags, int ksm, bool read_only, bool dont_dump, int *open_fd)
605 {
606 // netdata_log_info("netdata_mmap('%s', %zu", filename, size);
@@ -671,6 +673,7 @@ cleanup:
673 close(fd);
674 }
675 if(mem == MAP_FAILED) return NULL;
676 + __atomic_add_fetch(&netdata_mmap_count, 1, __ATOMIC_RELAXED);
677 errno_clear();
678 return mem;
679 }
@@ -679,7 +682,10 @@ int netdata_munmap(void *ptr, size_t size) {
682 #ifdef NETDATA_TRACE_ALLOCATIONS
683 malloc_trace_munmap(size);
684 #endif
682 - return munmap(ptr, size);
685 + int rc = munmap(ptr, size);
686 + if(rc == 0)
687 + __atomic_sub_fetch(&netdata_mmap_count, 1, __ATOMIC_RELAXED);
688 + return rc;
689 }
690
691 char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
src/libnetdata/libnetdata.h
+1
@@ -68,6 +68,7 @@ void posix_memfree(void *ptr);
68 void json_escape_string(char *dst, const char *src, size_t size);
69 void json_fix_string(char *s);
70
71 +extern size_t netdata_mmap_count;
72 void *netdata_mmap(const char *filename, size_t size, int flags, int ksm, bool read_only, bool dont_dump, int *open_fd);
73 int netdata_munmap(void *ptr, size_t size);
74 int memory_file_save(const char *filename, void *mem, size_t size);