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);