From e8b3c968037dff4a35de75272998333ac382e51d Mon Sep 17 00:00:00 2001 From: "Costa Tsaousis (ktsaou)" Date: Thu, 2 Apr 2015 23:11:46 +0300 Subject: [PATCH] added support for re-usable procfile, to eliminate the repeating memory allocations on apps.plugin --- src/plugins.d/apps_plugin.c | 34 ++++++++++++---------- src/procfile.c | 57 +++++++++++++++++++++++++++++-------- src/procfile.h | 11 +++++-- 3 files changed, 73 insertions(+), 29 deletions(-) diff --git a/src/plugins.d/apps_plugin.c b/src/plugins.d/apps_plugin.c index 2be7cf8c..19b6ae6f 100755 --- a/src/plugins.d/apps_plugin.c +++ b/src/plugins.d/apps_plugin.c @@ -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(); diff --git a/src/procfile.c b/src/procfile.c index ea18cb20..780cd733 100755 --- a/src/procfile.c +++ b/src/procfile.c @@ -20,10 +20,21 @@ #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 diff --git a/src/procfile.h b/src/procfile.h index f9bcd95b..b360f444 100755 --- a/src/procfile.h +++ b/src/procfile.h @@ -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) -- 2.39.2