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;