reduce netdata virtual memory size by setting MALLOC_ARENA_MAX; portable way of detecting mallinfo() and mallopt()
Costa Tsaousis (ktsaou) committed
Sep 30, 2016 at 23:19 UTC
9c9b9973fd36c382705b9f415f725b8dcf6edd33
6 files changed
+146
-68
configure.ac
+2
@@ -88,6 +88,8 @@ AC_TYPE_UINT16_T
88
AC_TYPE_UINT32_T
89
AC_C_INLINE
90
AC_FUNC_STRERROR_R
91
+AC_C_MALLOPT
92
+AC_C_MALLINFO
93
AC_C__GENERIC
94
AC_C___ATOMIC
95
AC_CHECK_SIZEOF([void *])
m4/ax_c_mallinfo.m4
new
+21
@@ -0,0 +1,21 @@
1
+# AC_C_MALLINFO
2
+# -------------
3
+# Define HAVE_C_MALLINFO if mallinfo() works.
4
+AN_IDENTIFIER([mallinfo], [AC_C_MALLINFO])
5
+AC_DEFUN([AC_C_MALLINFO],
6
+[AC_CACHE_CHECK([for mallinfo], ac_cv_c_mallinfo,
7
+[AC_LINK_IFELSE(
8
+ [AC_LANG_SOURCE(
9
+ [[#include <malloc.h>
10
+ int main(int argc, char **argv) {
11
+ struct mallinfo mi = mallinfo();
12
+ printf("%d%d%d\n", mi.uordblks, mi.hblkhd, mi.arena);
13
+ }
14
+ ]])],
15
+ [ac_cv_c_mallinfo=yes],
16
+ [ac_cv_c_mallinfo=no])])
17
+if test $ac_cv_c_mallinfo = yes; then
18
+ AC_DEFINE([HAVE_C_MALLINFO], 1,
19
+ [Define to 1 if glibc mallinfo exists.])
20
+fi
21
+])# AC_C_MALLINFO
m4/ax_c_mallopt.m4
new
+20
@@ -0,0 +1,20 @@
1
+# AC_C_MALLOPT
2
+# -------------
3
+# Define HAVE_C_MALLOPT if mallopt() works.
4
+AN_IDENTIFIER([mallopt], [AC_C_MALLOPT])
5
+AC_DEFUN([AC_C_MALLOPT],
6
+[AC_CACHE_CHECK([for mallopt], ac_cv_c_mallopt,
7
+[AC_LINK_IFELSE(
8
+ [AC_LANG_SOURCE(
9
+ [[#include <malloc.h>
10
+ int main(int argc, char **argv) {
11
+ mallopt(M_ARENA_MAX, 1);
12
+ }
13
+ ]])],
14
+ [ac_cv_c_mallopt=yes],
15
+ [ac_cv_c_mallopt=no])])
16
+if test $ac_cv_c_mallopt = yes; then
17
+ AC_DEFINE([HAVE_C_MALLOPT], 1,
18
+ [Define to 1 if glibc mallopt exists.])
19
+fi
20
+])# AC_C_MALLOPT
src/apps_plugin.c
+74
-61
@@ -66,23 +66,23 @@ struct target {
66
unsigned long long cstime;
67
unsigned long long cgtime;
68
unsigned long long num_threads;
69
- unsigned long long rss;
69
+ // unsigned long long rss;
70
71
unsigned long long statm_size;
72
unsigned long long statm_resident;
73
unsigned long long statm_share;
74
- unsigned long long statm_text;
75
- unsigned long long statm_lib;
76
- unsigned long long statm_data;
77
- unsigned long long statm_dirty;
74
+ // unsigned long long statm_text;
75
+ // unsigned long long statm_lib;
76
+ // unsigned long long statm_data;
77
+ // unsigned long long statm_dirty;
78
79
unsigned long long io_logical_bytes_read;
80
unsigned long long io_logical_bytes_written;
81
- unsigned long long io_read_calls;
82
- unsigned long long io_write_calls;
81
+ // unsigned long long io_read_calls;
82
+ // unsigned long long io_write_calls;
83
unsigned long long io_storage_bytes_read;
84
unsigned long long io_storage_bytes_written;
85
- unsigned long long io_cancelled_write_bytes;
85
+ // unsigned long long io_cancelled_write_bytes;
86
87
int *fds;
88
unsigned long long openfiles;
@@ -385,7 +385,7 @@ struct pid_stat {
385
// int64_t itrealvalue;
386
// unsigned long long starttime;
387
// unsigned long long vsize;
388
- unsigned long long rss;
388
+ // unsigned long long rss;
389
// unsigned long long rsslim;
390
// unsigned long long starcode;
391
// unsigned long long endcode;
@@ -411,26 +411,26 @@ struct pid_stat {
411
unsigned long long statm_size;
412
unsigned long long statm_resident;
413
unsigned long long statm_share;
414
- unsigned long long statm_text;
415
- unsigned long long statm_lib;
416
- unsigned long long statm_data;
417
- unsigned long long statm_dirty;
414
+ // unsigned long long statm_text;
415
+ // unsigned long long statm_lib;
416
+ // unsigned long long statm_data;
417
+ // unsigned long long statm_dirty;
418
419
unsigned long long io_logical_bytes_read_raw;
420
unsigned long long io_logical_bytes_written_raw;
421
- unsigned long long io_read_calls_raw;
422
- unsigned long long io_write_calls_raw;
421
+ // unsigned long long io_read_calls_raw;
422
+ // unsigned long long io_write_calls_raw;
423
unsigned long long io_storage_bytes_read_raw;
424
unsigned long long io_storage_bytes_written_raw;
425
- unsigned long long io_cancelled_write_bytes_raw;
425
+ // unsigned long long io_cancelled_write_bytes_raw;
426
427
unsigned long long io_logical_bytes_read;
428
unsigned long long io_logical_bytes_written;
429
- unsigned long long io_read_calls;
430
- unsigned long long io_write_calls;
429
+ // unsigned long long io_read_calls;
430
+ // unsigned long long io_write_calls;
431
unsigned long long io_storage_bytes_read;
432
unsigned long long io_storage_bytes_written;
433
- unsigned long long io_cancelled_write_bytes;
433
+ // unsigned long long io_cancelled_write_bytes;
434
435
int *fds; // array of fds it uses
436
int fds_size; // the size of the fds array
@@ -645,7 +645,7 @@ int read_proc_pid_stat(struct pid_stat *p) {
645
// p->itrealvalue = strtoull(procfile_lineword(ff, 0, 20), NULL, 10);
646
// p->starttime = strtoull(procfile_lineword(ff, 0, 21), NULL, 10);
647
// p->vsize = strtoull(procfile_lineword(ff, 0, 22), NULL, 10);
648
- p->rss = strtoull(procfile_lineword(ff, 0, 23), NULL, 10);
648
+ // p->rss = strtoull(procfile_lineword(ff, 0, 23), NULL, 10);
649
// p->rsslim = strtoull(procfile_lineword(ff, 0, 24), NULL, 10);
650
// p->starcode = strtoull(procfile_lineword(ff, 0, 25), NULL, 10);
651
// p->endcode = strtoull(procfile_lineword(ff, 0, 26), NULL, 10);
@@ -711,7 +711,7 @@ cleanup:
711
p->cstime = 0;
712
p->cgtime = 0;
713
p->num_threads = 0;
714
- p->rss = 0;
714
+ // p->rss = 0;
715
return 0;
716
}
717
@@ -735,10 +735,10 @@ int read_proc_pid_statm(struct pid_stat *p) {
735
p->statm_size = strtoull(procfile_lineword(ff, 0, 0), NULL, 10);
736
p->statm_resident = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
737
p->statm_share = strtoull(procfile_lineword(ff, 0, 2), NULL, 10);
738
- p->statm_text = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
739
- p->statm_lib = strtoull(procfile_lineword(ff, 0, 4), NULL, 10);
740
- p->statm_data = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
741
- p->statm_dirty = strtoull(procfile_lineword(ff, 0, 6), NULL, 10);
738
+ // p->statm_text = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
739
+ // p->statm_lib = strtoull(procfile_lineword(ff, 0, 4), NULL, 10);
740
+ // p->statm_data = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
741
+ // p->statm_dirty = strtoull(procfile_lineword(ff, 0, 6), NULL, 10);
742
743
return 1;
744
@@ -746,10 +746,10 @@ cleanup:
746
p->statm_size = 0;
747
p->statm_resident = 0;
748
p->statm_share = 0;
749
- p->statm_text = 0;
750
- p->statm_lib = 0;
751
- p->statm_data = 0;
752
- p->statm_dirty = 0;
749
+ // p->statm_text = 0;
750
+ // p->statm_lib = 0;
751
+ // p->statm_data = 0;
752
+ // p->statm_dirty = 0;
753
return 0;
754
}
755
@@ -784,13 +784,13 @@ int read_proc_pid_io(struct pid_stat *p) {
784
p->io_logical_bytes_written_raw = strtoull(procfile_lineword(ff, 1, 1), NULL, 10);
785
p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
786
787
- last = p->io_read_calls_raw;
788
- p->io_read_calls_raw = strtoull(procfile_lineword(ff, 2, 1), NULL, 10);
789
- p->io_read_calls = (p->io_read_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
787
+ // last = p->io_read_calls_raw;
788
+ // p->io_read_calls_raw = strtoull(procfile_lineword(ff, 2, 1), NULL, 10);
789
+ // p->io_read_calls = (p->io_read_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
790
791
- last = p->io_write_calls_raw;
792
- p->io_write_calls_raw = strtoull(procfile_lineword(ff, 3, 1), NULL, 10);
793
- p->io_write_calls = (p->io_write_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
791
+ // last = p->io_write_calls_raw;
792
+ // p->io_write_calls_raw = strtoull(procfile_lineword(ff, 3, 1), NULL, 10);
793
+ // p->io_write_calls = (p->io_write_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
794
795
last = p->io_storage_bytes_read_raw;
796
p->io_storage_bytes_read_raw = strtoull(procfile_lineword(ff, 4, 1), NULL, 10);
@@ -800,18 +800,18 @@ int read_proc_pid_io(struct pid_stat *p) {
800
p->io_storage_bytes_written_raw = strtoull(procfile_lineword(ff, 5, 1), NULL, 10);
801
p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
802
803
- last = p->io_cancelled_write_bytes_raw;
804
- p->io_cancelled_write_bytes_raw = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
805
- p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
803
+ // last = p->io_cancelled_write_bytes_raw;
804
+ // p->io_cancelled_write_bytes_raw = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
805
+ // p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
806
807
if(unlikely(global_iterations_counter == 1)) {
808
p->io_logical_bytes_read = 0;
809
p->io_logical_bytes_written = 0;
810
- p->io_read_calls = 0;
811
- p->io_write_calls = 0;
810
+ // p->io_read_calls = 0;
811
+ // p->io_write_calls = 0;
812
p->io_storage_bytes_read = 0;
813
p->io_storage_bytes_written = 0;
814
- p->io_cancelled_write_bytes = 0;
814
+ // p->io_cancelled_write_bytes = 0;
815
}
816
817
return 1;
@@ -819,11 +819,11 @@ int read_proc_pid_io(struct pid_stat *p) {
819
cleanup:
820
p->io_logical_bytes_read = 0;
821
p->io_logical_bytes_written = 0;
822
- p->io_read_calls = 0;
823
- p->io_write_calls = 0;
822
+ // p->io_read_calls = 0;
823
+ // p->io_write_calls = 0;
824
p->io_storage_bytes_read = 0;
825
p->io_storage_bytes_written = 0;
826
- p->io_cancelled_write_bytes = 0;
826
+ // p->io_cancelled_write_bytes = 0;
827
return 0;
828
}
829
@@ -1902,24 +1902,24 @@ long zero_all_targets(struct target *root) {
1902
w->cstime = 0;
1903
w->cgtime = 0;
1904
w->num_threads = 0;
1905
- w->rss = 0;
1905
+ // w->rss = 0;
1906
w->processes = 0;
1907
1908
w->statm_size = 0;
1909
w->statm_resident = 0;
1910
w->statm_share = 0;
1911
- w->statm_text = 0;
1912
- w->statm_lib = 0;
1913
- w->statm_data = 0;
1914
- w->statm_dirty = 0;
1911
+ // w->statm_text = 0;
1912
+ // w->statm_lib = 0;
1913
+ // w->statm_data = 0;
1914
+ // w->statm_dirty = 0;
1915
1916
w->io_logical_bytes_read = 0;
1917
w->io_logical_bytes_written = 0;
1918
- w->io_read_calls = 0;
1919
- w->io_write_calls = 0;
1918
+ // w->io_read_calls = 0;
1919
+ // w->io_write_calls = 0;
1920
w->io_storage_bytes_read = 0;
1921
w->io_storage_bytes_written = 0;
1922
- w->io_cancelled_write_bytes = 0;
1922
+ // w->io_cancelled_write_bytes = 0;
1923
}
1924
1925
return count;
@@ -1944,23 +1944,23 @@ void aggregate_pid_on_target(struct target *w, struct pid_stat *p, struct target
1944
w->minflt += p->minflt;
1945
w->majflt += p->majflt;
1946
1947
- w->rss += p->rss;
1947
+ // w->rss += p->rss;
1948
1949
w->statm_size += p->statm_size;
1950
w->statm_resident += p->statm_resident;
1951
w->statm_share += p->statm_share;
1952
- w->statm_text += p->statm_text;
1953
- w->statm_lib += p->statm_lib;
1954
- w->statm_data += p->statm_data;
1955
- w->statm_dirty += p->statm_dirty;
1952
+ // w->statm_text += p->statm_text;
1953
+ // w->statm_lib += p->statm_lib;
1954
+ // w->statm_data += p->statm_data;
1955
+ // w->statm_dirty += p->statm_dirty;
1956
1957
w->io_logical_bytes_read += p->io_logical_bytes_read;
1958
w->io_logical_bytes_written += p->io_logical_bytes_written;
1959
- w->io_read_calls += p->io_read_calls;
1960
- w->io_write_calls += p->io_write_calls;
1959
+ // w->io_read_calls += p->io_read_calls;
1960
+ // w->io_write_calls += p->io_write_calls;
1961
w->io_storage_bytes_read += p->io_storage_bytes_read;
1962
w->io_storage_bytes_written += p->io_storage_bytes_written;
1963
- w->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
1963
+ // w->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
1964
1965
w->processes++;
1966
w->num_threads += p->num_threads;
@@ -2433,6 +2433,13 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2433
}
2434
send_END();
2435
2436
+ send_BEGIN(type, "vmem", usec);
2437
+ for (w = root; w ; w = w->next) {
2438
+ if(unlikely(w->exposed))
2439
+ send_SET(w->name, w->statm_size);
2440
+ }
2441
+ send_END();
2442
+
2443
send_BEGIN(type, "minor_faults", usec);
2444
for (w = root; w ; w = w->next) {
2445
if(unlikely(w->exposed))
@@ -2529,7 +2536,13 @@ void send_charts_updates_to_netdata(struct target *root, const char *type, const
2536
buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, hz * RATES_DETAIL / 100, w->hidden ? "hidden" : "");
2537
}
2538
2532
- buffer_sprintf(output, "CHART %s.mem '' '%s Dedicated Memory (w/o shared)' 'MB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every);
2539
+ buffer_sprintf(output, "CHART %s.mem '' '%s Real Memory (w/o shared)' 'MB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every);
2540
+ for (w = root; w ; w = w->next) {
2541
+ if(unlikely(w->exposed))
2542
+ buffer_sprintf(output, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L);
2543
+ }
2544
+
2545
+ buffer_sprintf(output, "CHART %s.vmem '' '%s Virtual Memory Size' 'MB' mem %s.vmem stacked 20004 %d\n", type, title, type, update_every);
2546
for (w = root; w ; w = w->next) {
2547
if(unlikely(w->exposed))
2548
buffer_sprintf(output, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L);
src/main.c
+10
-2
@@ -286,8 +286,6 @@ int main(int argc, char **argv)
286
// set the name for logging
287
program_name = "netdata";
288
289
- // parse command line.
290
-
289
// parse depercated options
290
// TODO: Remove this block with the next major release.
291
{
@@ -409,6 +407,16 @@ int main(int argc, char **argv)
407
load_config(NULL, 0);
408
409
{
410
+ char *pmax = config_get("global", "glibc malloc arena max for plugins", "1");
411
+ if(pmax && *pmax)
412
+ setenv("MALLOC_ARENA_MAX", pmax, 1);
413
+
414
+#if defined(HAVE_C_MALLOPT)
415
+ int i = config_get_number("global", "glibc malloc arena max for netdata", 1);
416
+ if(i > 0)
417
+ mallopt(M_ARENA_MAX, 1);
418
+#endif
419
+
420
char *config_dir = config_get("global", "config directory", CONFIG_DIR);
421
422
// prepare configuration environment variables for the plugins
src/web_server.c
+19
-5
@@ -10,21 +10,35 @@ int web_server_mode = WEB_SERVER_MODE_MULTI_THREADED;
10
#ifdef NETDATA_INTERNAL_CHECKS
11
static void log_allocations(void)
12
{
13
- static int mem = 0;
13
+#ifdef HAVE_C_MALLINFO
14
+ static int heap = 0, used = 0, mmap = 0;
15
16
struct mallinfo mi;
17
18
mi = mallinfo();
18
- if(mi.uordblks > mem) {
19
+ if(mi.uordblks > used) {
20
int clients = 0;
21
struct web_client *w;
22
for(w = web_clients; w ; w = w->next) clients++;
23
23
- info("Allocated memory increased from %d to %d (increased by %d bytes). There are %d web clients connected.", mem, mi.uordblks, mi.uordblks - mem, clients);
24
- mem = mi.uordblks;
24
+ info("Allocated memory: used %d KB (+%d B), mmap %d KB (+%d B), heap %d KB (+%d B). %d web clients connected.",
25
+ mi.uordblks / 1024,
26
+ mi.uordblks - used,
27
+ mi.hblkhd / 1024,
28
+ mi.hblkhd - mmap,
29
+ mi.arena / 1024,
30
+ mi.arena - heap,
31
+ clients);
32
+
33
+ used = mi.uordblks;
34
+ heap = mi.arena;
35
+ mmap = mi.hblkhd;
36
}
37
+#else /* ! HAVE_C_MALLINFO */
38
+ ;
39
+#endif /* ! HAVE_C_MALLINFO */
40
}
27
-#endif
41
+#endif /* NETDATA_INTERNAL_CHECKS */
42
43
#ifndef HAVE_ACCEPT4
44
int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) {