@cryptotaxi247 / netdata-1 / commits / ee7b844c0

fix unecessary calls to realloc(); added memory allocations logger - enabled with -DNETDATA_LOG_ALLOCATIONS=1

Costa Tsaousis committed Sep 30, 2016 at 14:49 UTC ee7b844c041ec1453684dedefd3aed9e7de00c4d
6 files changed +158 -9
CMakeLists.txt
+1 -1
@@ -7,7 +7,7 @@ project(netdata C)
7
8 find_package (Threads)
9
10 -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat-signedness -Werror=format-security")
10 +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat-signedness -Werror=format-security -DNETDATA_INTERNAL_CHECKS=1")
11
12 set(NETDATA_SOURCE_FILES
13 src/appconfig.c
src/common.c
+116
@@ -14,31 +14,141 @@ volatile sig_atomic_t netdata_exit = 0;
14 // its lifetime), these can be used to override the default system allocation
15 // routines.
16
17 +#ifdef NETDATA_LOG_ALLOCATIONS
18 +static struct memory_statistics {
19 + size_t malloc_calls_made;
20 + size_t calloc_calls_made;
21 + size_t realloc_calls_made;
22 + size_t strdup_calls_made;
23 + size_t free_calls_made;
24 + size_t memory_calls_made;
25 + size_t allocated_memory;
26 + size_t mmapped_memory;
27 +} memory_statistics = {
28 + 0, 0, 0, 0, 0, 0, 0, 0
29 +};
30 +
31 +static inline void print_allocations(const char *file, const char *function, const unsigned long line) {
32 + static struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 };
33 +
34 + //if(unlikely(!(memory_statistics.memory_calls_made % 5))) {
35 + fprintf(stderr, "(%04lu@%-10.10s:%-15.15s): Allocated %zu KB (+%zu B), mmapped %zu KB (+%zu B): malloc %zu (+%zu), calloc %zu (+%zu), realloc %zu (+%zu), strdup %zu (+%zu), free %zu (+%zu)\n",
36 + line, file, function,
37 + (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory,
38 + (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory,
39 + memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made,
40 + memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made,
41 + memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made,
42 + memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made,
43 + memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made
44 + );
45 +
46 + memcpy(&old, &memory_statistics, sizeof(struct memory_statistics));
47 + //}
48 +}
49 +
50 +static inline void malloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
51 + memory_statistics.memory_calls_made++;
52 + memory_statistics.malloc_calls_made++;
53 + memory_statistics.allocated_memory += size;
54 + print_allocations(file, function, line);
55 +}
56 +
57 +static inline void mmap_accounting(size_t size) {
58 + memory_statistics.memory_calls_made++;
59 + memory_statistics.mmapped_memory += size;
60 +}
61 +
62 +static inline void calloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
63 + memory_statistics.memory_calls_made++;
64 + memory_statistics.calloc_calls_made++;
65 + memory_statistics.allocated_memory += size;
66 + print_allocations(file, function, line);
67 +}
68 +
69 +static inline void realloc_accounting(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
70 + (void)ptr;
71 +
72 + memory_statistics.memory_calls_made++;
73 + memory_statistics.realloc_calls_made++;
74 + memory_statistics.allocated_memory += size;
75 + print_allocations(file, function, line);
76 +}
77 +
78 +static inline void strdup_accounting(const char *file, const char *function, const unsigned long line, const char *s) {
79 + memory_statistics.memory_calls_made++;
80 + memory_statistics.strdup_calls_made++;
81 + memory_statistics.allocated_memory += strlen(s) + 1;
82 + print_allocations(file, function, line);
83 +}
84 +
85 +static inline void free_accounting(const char *file, const char *function, const unsigned long line, void *ptr) {
86 + (void)file;
87 + (void)function;
88 + (void)line;
89 +
90 + if(likely(ptr)) {
91 + memory_statistics.memory_calls_made++;
92 + memory_statistics.free_calls_made++;
93 + }
94 +}
95 +#endif
96 +
97 +#ifdef NETDATA_LOG_ALLOCATIONS
98 +char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) {
99 + strdup_accounting(file, function, line, s);
100 +#else
101 char *strdupz(const char *s) {
102 +#endif
103 +
104 char *t = strdup(s);
105 if (unlikely(!t)) fatal("Cannot strdup() string '%s'", s);
106 return t;
107 }
108
109 +#ifdef NETDATA_LOG_ALLOCATIONS
110 +void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size) {
111 + malloc_accounting(file, function, line, size);
112 +#else
113 void *mallocz(size_t size) {
114 +#endif
115 +
116 void *p = malloc(size);
117 if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", size);
118 return p;
119 }
120
121 +#ifdef NETDATA_LOG_ALLOCATIONS
122 +void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size) {
123 + calloc_accounting(file, function, line, nmemb * size);
124 +#else
125 void *callocz(size_t nmemb, size_t size) {
126 +#endif
127 +
128 void *p = calloc(nmemb, size);
129 if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", nmemb * size);
130 return p;
131 }
132
133 +#ifdef NETDATA_LOG_ALLOCATIONS
134 +void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
135 + realloc_accounting(file, function, line, ptr, size);
136 +#else
137 void *reallocz(void *ptr, size_t size) {
138 +#endif
139 +
140 void *p = realloc(ptr, size);
141 if (unlikely(!p)) fatal("Cannot re-allocate memory to %zu bytes.", size);
142 return p;
143 }
144
145 +#ifdef NETDATA_LOG_ALLOCATIONS
146 +void freez_int(const char *file, const char *function, const unsigned long line, void *ptr) {
147 + free_accounting(file, function, line, ptr);
148 +#else
149 void freez(void *ptr) {
150 +#endif
151 +
152 free(ptr);
153 }
154
@@ -775,6 +885,9 @@ void *mymmap(const char *filename, size_t size, int flags, int ksm) {
885 mem = NULL;
886 }
887 else {
888 +#ifdef NETDATA_LOG_ALLOCATIONS
889 + mmap_accounting(size);
890 +#endif
891 int advise = MADV_SEQUENTIAL | MADV_DONTFORK;
892 if (flags & MAP_SHARED) advise |= MADV_WILLNEED;
893
@@ -804,6 +917,9 @@ void *mymmap(const char *filename, size_t size, int flags, int ksm) {
917 mem = NULL;
918 }
919 else {
920 +#ifdef NETDATA_LOG_ALLOCATIONS
921 + mmap_accounting(size);
922 +#endif
923 if (lseek(fd, 0, SEEK_SET) == 0) {
924 if (read(fd, mem, size) != (ssize_t) size)
925 error("Cannot read from file '%s'", filename);
src/common.h
+15 -1
@@ -131,11 +131,25 @@ extern int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args);
131 extern int snprintfz(char *dst, size_t n, const char *fmt, ...) __attribute__ (( format (printf, 3, 4)));
132
133 // memory allocation functions that handle failures
134 +#ifdef NETDATA_LOG_ALLOCATIONS
135 +#define strdupz(s) strdupz_int(__FILE__, __FUNCTION__, __LINE__, s)
136 +#define callocz(nmemb, size) callocz_int(__FILE__, __FUNCTION__, __LINE__, nmemb, size)
137 +#define mallocz(size) mallocz_int(__FILE__, __FUNCTION__, __LINE__, size)
138 +#define reallocz(ptr, size) reallocz_int(__FILE__, __FUNCTION__, __LINE__, ptr, size)
139 +#define freez(ptr) freez_int(__FILE__, __FUNCTION__, __LINE__, ptr)
140 +
141 +extern char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s);
142 +extern void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size);
143 +extern void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size);
144 +extern void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size);
145 +extern void freez_int(const char *file, const char *function, const unsigned long line, void *ptr);
146 +#else
147 extern char *strdupz(const char *s);
148 extern void *callocz(size_t nmemb, size_t size);
149 extern void *mallocz(size_t size);
137 -extern void freez(void *ptr);
150 extern void *reallocz(void *ptr, size_t size);
151 +extern void freez(void *ptr);
152 +#endif
153
154 extern void *mymmap(const char *filename, size_t size, int flags, int ksm);
155 extern int savememory(const char *filename, void *mem, size_t size);
src/proc_interrupts.c
+1 -2
@@ -21,8 +21,7 @@ static inline struct interrupt *get_interrupts_array(int lines, int cpus) {
21 static struct interrupt *irrs = NULL;
22 static int allocated = 0;
23
24 - if(lines < allocated) return irrs;
25 - else {
24 + if(lines > allocated) {
25 irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
26 allocated = lines;
27 }
src/proc_softirqs.c
+1 -2
@@ -21,8 +21,7 @@ static inline struct interrupt *get_interrupts_array(int lines, int cpus) {
21 static struct interrupt *irrs = NULL;
22 static int allocated = 0;
23
24 - if(lines < allocated) return irrs;
25 - else {
24 + if(lines > allocated) {
25 irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
26 allocated = lines;
27 }
src/rrd.c
+24 -3
@@ -425,6 +425,27 @@ void rrdset_reset(RRDSET *st)
425 memset(rd->values, 0, rd->entries * sizeof(storage_number));
426 }
427 }
428 +static long align_entries_to_pagesize(long entries) {
429 + if(entries < 5) entries = 5;
430 + if(entries > RRD_HISTORY_ENTRIES_MAX) entries = RRD_HISTORY_ENTRIES_MAX;
431 +
432 +#ifdef NETDATA_LOG_ALLOCATIONS
433 + long page = (size_t)sysconf(_SC_PAGESIZE);
434 +
435 + long size = sizeof(RRDDIM) + entries * sizeof(storage_number);
436 + if(size % page) {
437 + size -= (size % page);
438 + size += page;
439 +
440 + long n = (size - sizeof(RRDDIM)) / sizeof(storage_number);
441 + return n;
442 + }
443 +
444 + return entries;
445 +#else
446 + return entries;
447 +#endif
448 +}
449
450 RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, long priority, int update_every, int chart_type)
451 {
@@ -450,9 +471,9 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
471 return st;
472 }
473
453 - long entries = config_get_number(fullid, "history", rrd_default_history_entries);
454 - if(entries < 5) entries = config_set_number(fullid, "history", 5);
455 - if(entries > RRD_HISTORY_ENTRIES_MAX) entries = config_set_number(fullid, "history", RRD_HISTORY_ENTRIES_MAX);
474 + long rentries = config_get_number(fullid, "history", rrd_default_history_entries);
475 + long entries = align_entries_to_pagesize(rentries);
476 + if(entries != rentries) entries = config_set_number(fullid, "history", entries);
477
478 int enabled = config_get_boolean(fullid, "enabled", 1);
479 if(!enabled) entries = 5;