@cryptotaxi247 / netdata-1 / commits / ed44ce7b8

tc: optimized memory usage

Costa Tsaousis (ktsaou) committed Apr 4, 2015 at 05:57 UTC ed44ce7b87de9070f5ecb27a15198807cd0c55d5
2 files changed +85 -29
src/daemon.c
+2 -2
@@ -69,9 +69,9 @@ char pidfile[FILENAME_MAX + 1] = "";
69 void prepare_rundir() {
70 if(getuid() != 0) {
71 mkdir("/run/user", 0775);
72 - snprintf(rundir, FILENAME_MAX, "/run/user/%d", getpid());
72 + snprintf(rundir, FILENAME_MAX, "/run/user/%d", getuid());
73 mkdir(rundir, 0775);
74 - snprintf(rundir, FILENAME_MAX, "/run/user/%d/netdata", getpid());
74 + snprintf(rundir, FILENAME_MAX, "/run/user/%d/netdata", getuid());
75 }
76
77 snprintf(pidfile, FILENAME_MAX, "%s/netdata.pid", rundir);
src/plugin_tc.c
+83 -27
@@ -38,9 +38,11 @@ struct tc_class {
38 char isleaf;
39 unsigned long long bytes;
40
41 - char updated;
41 + char updated; // updated bytes
42 + char seen; // seen in the tc list (even without bytes)
43
44 struct tc_class *next;
45 + struct tc_class *prev;
46 };
47
48 struct tc_device {
@@ -112,6 +114,48 @@ static struct tc_class *tc_class_index_find(struct tc_device *st, const char *id
114
115 // ----------------------------------------------------------------------------
116
117 +static void tc_class_free(struct tc_device *n, struct tc_class *c) {
118 + debug(D_TC_LOOP, "Removing from device '%s' class '%s', parentid '%s', leafid '%s', seen=%d", n->id, c->id, c->parentid?c->parentid:"", c->leafid?c->leafid:"", c->seen);
119 +
120 + if(c->next) c->next->prev = c->prev;
121 + if(c->prev) c->prev->next = c->next;
122 + if(n->classes == c) n->classes = c->next;
123 +
124 + tc_class_index_del(n, c);
125 +
126 + if(c->id) free(c->id);
127 + if(c->name) free(c->name);
128 + if(c->leafid) free(c->leafid);
129 + if(c->parentid) free(c->parentid);
130 +
131 + free(c);
132 +}
133 +
134 +static void tc_device_classes_cleanup(struct tc_device *d) {
135 + static int cleanup_every = 999;
136 +
137 + if(cleanup_every > 0) {
138 + cleanup_every = -config_get_number("plugin:tc", "cleanup unused classes every", 60);
139 + if(cleanup_every > 0) cleanup_every = -cleanup_every;
140 + if(cleanup_every == 0) cleanup_every = -1;
141 + }
142 +
143 + struct tc_class *c = d->classes;
144 + while(c) {
145 + if(c->seen < cleanup_every) {
146 + struct tc_class *nc = c->next;
147 + tc_class_free(d, c);
148 + c = nc;
149 + }
150 + else c = c->next;
151 +
152 + if(c) {
153 + c->updated = 0;
154 + c->seen--;
155 + }
156 + }
157 +}
158 +
159 static void tc_device_commit(struct tc_device *d)
160 {
161 static int enable_new_interfaces = -1;
@@ -121,7 +165,7 @@ static void tc_device_commit(struct tc_device *d)
165 // we only need to add leaf classes
166 struct tc_class *c, *x;
167
124 - // set them all as leafs without parent
168 + // set all classes
169 for(c = d->classes ; c ; c = c->next) {
170 c->isleaf = 1;
171 c->hasparent = 0;
@@ -134,10 +178,12 @@ static void tc_device_commit(struct tc_device *d)
178 for(x = d->classes ; x ; x = x->next) {
179 if(!x->updated) continue;
180
181 + if(c == x) continue;
182 +
183 if(x->parentid && (
184 ( c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) ||
185 (c->leafid && c->leaf_hash == x->parent_hash && strcmp(c->leafid, x->parentid) == 0))) {
140 - // debug(D_TC_LOOP, "TC: In device '%s', class '%s' (leafid: '%s') has leaf the class '%s' (parentid: '%s').", d->name, c->name, c->leafid, x->name, x->parentid);
186 + // debug(D_TC_LOOP, "TC: In device '%s', class '%s' (leafid: '%s') has as leaf class '%s' (parentid: '%s').", d->name?d->name:d->id, c->name?c->name:c->id, c->leafid?c->leafid:c->id, x->name?x->name:x->id, x->parentid?x->parentid:x->id);
187 c->isleaf = 0;
188 x->hasparent = 1;
189 }
@@ -152,13 +198,15 @@ static void tc_device_commit(struct tc_device *d)
198 }
199 */
200
155 - // we need a device
201 + // we need at least a class
202 for(c = d->classes ; c ; c = c->next) {
203 + // debug(D_TC_LOOP, "TC: Device '%s', class '%s', isLeaf=%d, HasParent=%d, Seen=%d", d->name?d->name:d->id, c->name?c->name:c->id, c->isleaf, c->hasparent, c->seen);
204 if(!c->updated) continue;
205 if(c->isleaf && c->hasparent) break;
206 }
207 if(!c) {
208 debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. No leaf classes.", d->name?d->name:d->id);
209 + tc_device_classes_cleanup(d);
210 return;
211 }
212
@@ -167,7 +215,7 @@ static void tc_device_commit(struct tc_device *d)
215 if(config_get_boolean("plugin:tc", var_name, enable_new_interfaces)) {
216 RRDSET *st = rrdset_find_bytype(RRD_TYPE_TC, d->id);
217 if(!st) {
170 - debug(D_TC_LOOP, "TC: Committing new TC device '%s'", d->name?d->name:d->id);
218 + debug(D_TC_LOOP, "TC: Creating new chart for device '%s'", d->name?d->name:d->id);
219
220 st = rrdset_create(RRD_TYPE_TC, d->id, d->name?d->name:d->id, d->family?d->family:d->id, "Class Usage", "kilobits/s", 1000, rrd_update_every, RRDSET_TYPE_STACKED);
221
@@ -179,6 +227,7 @@ static void tc_device_commit(struct tc_device *d)
227 }
228 }
229 else {
230 + debug(D_TC_LOOP, "TC: Updating chart for device '%s'", d->name?d->name:d->id);
231 rrdset_next_plugins(st);
232
233 if(d->name && strcmp(d->id, d->name) != 0) rrdset_set_name(st, d->name);
@@ -189,27 +238,32 @@ static void tc_device_commit(struct tc_device *d)
238
239 if(c->isleaf && c->hasparent) {
240 if(rrddim_set(st, c->id, c->bytes) != 0) {
241 + debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s'", st->id, c->id, c->name);
242
243 // new class, we have to add it
244 rrddim_add(st, c->id, c->name?c->name:c->id, 8, 1024 * rrd_update_every, RRDDIM_INCREMENTAL);
245 rrddim_set(st, c->id, c->bytes);
246 }
247 + else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", st->id, c->id);
248
249 // if it has a name, different to the id
250 if(c->name) {
251 // update the rrd dimension with the new name
252 RRDDIM *rd = rrddim_find(st, c->id);
202 - if(rd) rrddim_set_name(st, rd, c->name);
253 + if(rd) {
254 + debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", st->id, rd->id, c->name);
255 + rrddim_set_name(st, rd, c->name);
256 + }
257
258 free(c->name);
259 c->name = NULL;
260 }
261 }
208 -
209 - c->updated = 0;
262 }
263 rrdset_done(st);
264 }
265 +
266 + tc_device_classes_cleanup(d);
267 }
268
269 static void tc_device_set_class_name(struct tc_device *d, char *id, char *name)
@@ -219,7 +273,10 @@ static void tc_device_set_class_name(struct tc_device *d, char *id, char *name)
273 if(c->name) free(c->name);
274 c->name = NULL;
275
222 - if(name && *name && strcmp(c->id, name) != 0) c->name = strdup(name);
276 + if(name && *name && strcmp(c->id, name) != 0) {
277 + debug(D_TC_LOOP, "TC: Setting device '%s', class '%s' name to '%s'", d->id, id, name);
278 + c->name = strdup(name);
279 + }
280 }
281 }
282
@@ -227,14 +284,20 @@ static void tc_device_set_device_name(struct tc_device *d, char *name) {
284 if(d->name) free(d->name);
285 d->name = NULL;
286
230 - if(name && *name && strcmp(d->id, name) != 0) d->name = strdup(name);
287 + if(name && *name && strcmp(d->id, name) != 0) {
288 + debug(D_TC_LOOP, "TC: Setting device '%s' name to '%s'", d->id, name);
289 + d->name = strdup(name);
290 + }
291 }
292
293 static void tc_device_set_device_family(struct tc_device *d, char *family) {
294 if(d->family) free(d->family);
295 d->family = NULL;
296
237 - if(family && *family && strcmp(d->id, family) != 0) d->family = strdup(family);
297 + if(family && *family && strcmp(d->id, family) != 0) {
298 + debug(D_TC_LOOP, "TC: Setting device '%s' family to '%s'", d->id, family);
299 + d->family = strdup(family);
300 + }
301 // no need for null termination - it is already null
302 }
303
@@ -243,6 +306,7 @@ static struct tc_device *tc_device_create(char *id)
306 struct tc_device *d = tc_device_index_find(id, 0);
307
308 if(!d) {
309 + debug(D_TC_LOOP, "TC: Creating device '%s'", id);
310
311 d = calloc(1, sizeof(struct tc_device));
312 if(!d) {
@@ -264,16 +328,18 @@ static struct tc_device *tc_device_create(char *id)
328
329 static struct tc_class *tc_class_add(struct tc_device *n, char *id, char *parentid, char *leafid)
330 {
267 - // fprintf(stderr, "Adding class id '%s', parentid '%s', leafid '%s'\n", id, parentid, leafid);
268 -
331 struct tc_class *c = tc_class_index_find(n, id, 0);
332 +
333 if(!c) {
334 + debug(D_TC_LOOP, "TC: Creating in device '%s', class id '%s', parentid '%s', leafid '%s'", n->id, id, parentid?parentid:"", leafid?leafid:"");
335 +
336 c = calloc(1, sizeof(struct tc_class));
337 if(!c) {
338 fatal("Cannot allocate memory for tc class");
339 return NULL;
340 }
341
342 + if(n->classes) n->classes->prev = c;
343 c->next = n->classes;
344 n->classes = c;
345
@@ -297,26 +363,16 @@ static struct tc_class *tc_class_add(struct tc_device *n, char *id, char *parent
363 tc_class_index_add(n, c);
364 }
365
366 + c->seen = 1;
367 +
368 return(c);
369 }
370 /*
303 -static void tc_class_free_all(struct tc_device *n, struct tc_class *c)
304 -{
305 - if(c->next) tc_class_free_all(n, c->next);
306 - tc_class_index_del(n, c);
307 -
308 - if(c->id) free(c->id);
309 - if(c->name) free(c->name);
310 - if(c->leafid) free(c->leafid);
311 - if(c->parentid) free(c->parentid);
312 -
313 - free(c);
314 -}
315 -
371 static void tc_device_free(struct tc_device *n)
372 {
373 tc_device_index_del(n);
319 - if(n->classes) tc_class_free_all(n, n->classes);
374 +
375 + while(n->classes) tc_class_free(n, n->classes);
376
377 if(n->id) free(n->id);
378 if(n->name) free(n->name);