]> arthur.barton.de Git - netdata.git/commitdiff
added support for re-usable procfile, to eliminate the repeating memory allocations...
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Thu, 2 Apr 2015 20:11:46 +0000 (23:11 +0300)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Thu, 2 Apr 2015 20:11:46 +0000 (23:11 +0300)
src/plugins.d/apps_plugin.c
src/procfile.c
src/procfile.h

index 2be7cf8c7f64bc31b119ef01cf6f9c96113fca53..19b6ae6f0bb809a64db6e9cb8984a254bc44c167 100755 (executable)
@@ -197,15 +197,17 @@ char *strdup_debug(const char *file, int line, const char *function, const char
 // ----------------------------------------------------------------------------
 // helper functions
 
+procfile *ff = NULL;
+
 long get_processors(void) {
        int processors = 0;
 
-       procfile *ff = procfile_open("/proc/stat", "");
+       ff = procfile_reopen(ff, "/proc/stat", "");
        if(!ff) return 1;
 
        ff = procfile_readall(ff);
        if(!ff) {
-               procfile_close(ff);
+               // procfile_close(ff);
                return 1;
        }
 
@@ -218,26 +220,26 @@ long get_processors(void) {
        processors--;
        if(processors < 1) processors = 1;
 
-       procfile_close(ff);
+       // procfile_close(ff);
        return processors;
 }
 
 long get_pid_max(void) {
        long mpid = 32768;
 
-       procfile *ff = procfile_open("/proc/sys/kernel/pid_max", "");
+       ff = procfile_reopen(ff, "/proc/sys/kernel/pid_max", "");
        if(!ff) return mpid;
 
        ff = procfile_readall(ff);
        if(!ff) {
-               procfile_close(ff);
+               // procfile_close(ff);
                return mpid;
        }
 
        mpid = atol(procfile_lineword(ff, 0, 0));
        if(mpid) mpid = 32768;
 
-       procfile_close(ff);
+       // procfile_close(ff);
        return mpid;
 }
 
@@ -608,12 +610,12 @@ int read_proc_pid_stat(struct pid_stat *p) {
 
        snprintf(filename, FILENAME_MAX, "/proc/%d/stat", p->pid);
 
-       procfile *ff = procfile_open(filename, "");
+       ff = procfile_reopen(ff, filename, "");
        if(!ff) return 1;
 
        ff = procfile_readall(ff);
        if(!ff) {
-               procfile_close(ff);
+               // procfile_close(ff);
                return 1;
        }
 
@@ -688,7 +690,7 @@ int read_proc_pid_stat(struct pid_stat *p) {
 
        if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: VALUES: %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, threads=%d\n", p->comm, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
 
-       procfile_close(ff);
+       // procfile_close(ff);
        return 0;
 }
 
@@ -697,12 +699,12 @@ int read_proc_pid_statm(struct pid_stat *p) {
 
        snprintf(filename, FILENAME_MAX, "/proc/%d/statm", p->pid);
 
-       procfile *ff = procfile_open(filename, "");
+       ff = procfile_reopen(ff, filename, "");
        if(!ff) return 1;
 
        ff = procfile_readall(ff);
        if(!ff) {
-               procfile_close(ff);
+               // procfile_close(ff);
                return 1;
        }
 
@@ -716,7 +718,7 @@ int read_proc_pid_statm(struct pid_stat *p) {
        p->statm_data                   = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
        p->statm_dirty                  = strtoull(procfile_lineword(ff, 0, 6), NULL, 10);
 
-       procfile_close(ff);
+       // procfile_close(ff);
        return 0;
 }
 
@@ -725,12 +727,12 @@ int read_proc_pid_io(struct pid_stat *p) {
 
        snprintf(filename, FILENAME_MAX, "/proc/%d/io", p->pid);
 
-       procfile *ff = procfile_open(filename, ":");
+       ff = procfile_reopen(ff, filename, ":");
        if(!ff) return 1;
 
        ff = procfile_readall(ff);
        if(!ff) {
-               procfile_close(ff);
+               // procfile_close(ff);
                return 1;
        }
 
@@ -744,7 +746,7 @@ int read_proc_pid_io(struct pid_stat *p) {
        p->io_storage_bytes_written     = strtoull(procfile_lineword(ff, 5, 1), NULL, 10);
        p->io_cancelled_write_bytes             = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
 
-       procfile_close(ff);
+       // procfile_close(ff);
        return 0;
 }
 
@@ -1893,6 +1895,8 @@ int main(int argc, char **argv)
 
        info("apps.plugin: starting...");
 
+       procfile_adaptive_initial_allocation = 1;
+
        unsigned long started_t = time(NULL), current_t;
        Hertz = get_hertz();
        pid_max = get_pid_max();
index ea18cb207d82e532fa64792f5ae17433d1356bc7..780cd73370a302eab6a1a5044d206d36bca89729 100755 (executable)
 
 #define PF_PREFIX "PROCFILE"
 
+#define PFWORDS_INCREASE_STEP 200
+#define PFLINES_INCREASE_STEP 10
+#define PROCFILE_INCREMENT_BUFFER 512
+
+int procfile_adaptive_initial_allocation = 0;
+
+// if adaptive allocation is set, these store the
+// max values we have seen so far
+uint32_t procfile_max_lines = PFLINES_INCREASE_STEP;
+uint32_t procfile_max_words = PFWORDS_INCREASE_STEP;
+size_t procfile_max_allocation = PROCFILE_INCREMENT_BUFFER;
+
 // ----------------------------------------------------------------------------
 // An array of words
 
-#define PFWORDS_INCREASE_STEP 200
 
 pfwords *pfwords_add(pfwords *fw, char *str) {
        // debug(D_PROCFILE, PF_PREFIX ":       adding word No %d: '%s'", fw->len, str);
@@ -49,11 +60,13 @@ pfwords *pfwords_add(pfwords *fw, char *str) {
 pfwords *pfwords_new(void) {
        // debug(D_PROCFILE, PF_PREFIX ":       initializing words");
 
-       pfwords *new = malloc(sizeof(pfwords) + PFWORDS_INCREASE_STEP * sizeof(char *));
+       uint32_t size = (procfile_adaptive_initial_allocation) ? procfile_max_words : PFWORDS_INCREASE_STEP;
+
+       pfwords *new = malloc(sizeof(pfwords) + size * sizeof(char *));
        if(!new) return NULL;
 
        new->len = 0;
-       new->size = PFWORDS_INCREASE_STEP;
+       new->size = size;
        return new;
 }
 
@@ -72,8 +85,6 @@ void pfwords_free(pfwords *fw) {
 // ----------------------------------------------------------------------------
 // An array of lines
 
-#define PFLINES_INCREASE_STEP 10
-
 pflines *pflines_add(pflines *fl, uint32_t first_word) {
        // debug(D_PROCFILE, PF_PREFIX ":       adding line %d at word %d", fl->len, first_word);
 
@@ -99,11 +110,13 @@ pflines *pflines_add(pflines *fl, uint32_t first_word) {
 pflines *pflines_new(void) {
        // debug(D_PROCFILE, PF_PREFIX ":       initializing lines");
 
-       pflines *new = malloc(sizeof(pflines) + PFLINES_INCREASE_STEP * sizeof(ffline));
+       uint32_t size = (procfile_adaptive_initial_allocation) ? procfile_max_words : PFLINES_INCREASE_STEP;
+
+       pflines *new = malloc(sizeof(pflines) + size * sizeof(ffline));
        if(!new) return NULL;
 
        new->len = 0;
-       new->size = PFLINES_INCREASE_STEP;
+       new->size = size;
        return new;
 }
 
@@ -123,9 +136,6 @@ void pflines_free(pflines *fl) {
 // ----------------------------------------------------------------------------
 // The procfile
 
-#define PROCFILE_INITIAL_BUFFER 256
-#define PROCFILE_INCREMENT_BUFFER 512
-
 #define PF_CHAR_IS_SEPARATOR   0
 #define PF_CHAR_IS_NEWLINE     1
 #define PF_CHAR_IS_WORD                2
@@ -264,6 +274,12 @@ procfile *procfile_readall(procfile *ff) {
 
        ff = procfile_parser(ff);
 
+       if(procfile_adaptive_initial_allocation) {
+               if(ff->len > procfile_max_allocation) procfile_max_allocation = ff->len;
+               if(ff->lines->len > procfile_max_lines) procfile_max_lines = ff->lines->len;
+               if(ff->words->len > procfile_max_words) procfile_max_words = ff->words->len;
+       }
+
        debug(D_PROCFILE, "File '%s' updated.", ff->filename);
        return ff;
 }
@@ -277,7 +293,8 @@ procfile *procfile_open(const char *filename, const char *separators) {
                return NULL;
        }
 
-       procfile *ff = malloc(sizeof(procfile) + PROCFILE_INITIAL_BUFFER);
+       size_t size = (procfile_adaptive_initial_allocation) ? procfile_max_allocation : PROCFILE_INCREMENT_BUFFER;
+       procfile *ff = malloc(sizeof(procfile) + size);
        if(!ff) {
                error(PF_PREFIX ": Cannot allocate memory for file '%s'. Reason: %s", filename, strerror(errno));
                close(fd);
@@ -288,7 +305,7 @@ procfile *procfile_open(const char *filename, const char *separators) {
        ff->filename[FILENAME_MAX] = '\0';
 
        ff->fd = fd;
-       ff->size = PROCFILE_INITIAL_BUFFER;
+       ff->size = size;
        ff->len = 0;
 
        ff->lines = pflines_new();
@@ -315,6 +332,22 @@ procfile *procfile_open(const char *filename, const char *separators) {
        return ff;
 }
 
+procfile *procfile_reopen(procfile *ff, const char *filename, const char *separators) {
+       if(!ff) return procfile_open(filename, separators);
+
+       if(ff->fd != -1) close(ff->fd);
+
+       ff->fd = open(filename, O_RDONLY, 0666);
+       if(ff->fd == -1) {
+               procfile_close(ff);
+               return NULL;
+       }
+
+       strncpy(ff->filename, filename, FILENAME_MAX);
+       ff->filename[FILENAME_MAX] = '\0';
+
+       return ff;
+}
 
 // ----------------------------------------------------------------------------
 // example parsing of procfile data
index f9bcd95b6bdaaa0d7c0952e7373434f6dc095a3f..b360f4441972ab1b00d572e4a176c2ba25238174 100755 (executable)
@@ -58,8 +58,8 @@ typedef struct {
 typedef struct {
        char filename[FILENAME_MAX + 1];
        int fd;                 // the file desriptor
-       ssize_t len;            // the bytes we have placed into data
-       ssize_t size;           // the bytes we have allocated for data
+       size_t len;             // the bytes we have placed into data
+       size_t size;            // the bytes we have allocated for data
        pflines *lines;
        pfwords *words;
        char separators[256];
@@ -75,11 +75,18 @@ extern procfile *procfile_readall(procfile *ff);
 // open a /proc or /sys file
 extern procfile *procfile_open(const char *filename, const char *separators);
 
+// re-open a file
+// the separators argument is only used if ff == NULL
+extern procfile *procfile_reopen(procfile *ff, const char *filename, const char *separators);
+
 // example walk-through a procfile parsed file
 extern void procfile_print(procfile *ff);
 
 // ----------------------------------------------------------------------------
 
+// set this to 1, to have procfile adapt its initial buffer allocation to the max allocation used so far
+extern int procfile_adaptive_initial_allocation;
+
 // return the number of lines present
 #define procfile_lines(ff) (ff->lines->len)