@cryptotaxi247 / netdata-1 / commits / 9c9b9973f

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