diff options
author | Vito Caputo <vcaputo@gnugeneration.com> | 2017-03-21 17:08:03 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@gnugeneration.com> | 2017-03-21 17:08:03 -0700 |
commit | 21cdd99c77dd4dcc20c2c1a6a8868aef8e9285dc (patch) | |
tree | 2ec582333470b9f1593fb4a0e294b2ee153f3680 /src/libvmon | |
parent | 872fcd6219bb2d01685e4a3c5828c6f8789681c9 (diff) |
libvmon: use pread() instead of lseek()+read()
I had assumed pread wouldn't work on /proc files and that lseek to the
start was the only safe form of seeking, but this seems to be working
acceptably well even with buffer sizes of 2 requiring many sequential
reads per sample.
The lseek syscalls aren't free and it's nice to omit them entirely,
and we're essentially being sequential in our pread() use, and always
use a buffer that is large enough to fit everything in the first read
anyways.
Diffstat (limited to 'src/libvmon')
-rw-r--r-- | src/libvmon/vmon.c | 68 |
1 files changed, 27 insertions, 41 deletions
diff --git a/src/libvmon/vmon.c b/src/libvmon/vmon.c index 942d3cd..69c0059 100644 --- a/src/libvmon/vmon.c +++ b/src/libvmon/vmon.c @@ -75,22 +75,10 @@ static void try_closedir(DIR **dir) } -/* these have been wrapped to suppress syscall overhead when we have a bad file descriptor without cluttering the samplers with checks */ -static off_t try_lseek(int fd, off_t offset, int whence) +static ssize_t try_pread(int fd, void *buf, size_t count, off_t offset) { if (fd != -1) { - return lseek(fd, offset, whence); - } else { - errno = EBADF; - return fd; - } -} - - -static ssize_t try_read(int fd, void *buf, size_t count) -{ - if (fd != -1) { - return read(fd, buf, count); + return pread(fd, buf, count, offset); } else { errno = EBADF; return fd; @@ -135,7 +123,7 @@ static char * load_contents_fd(vmon_t *vmon, vmon_char_array_t *array, int fd, v int total = 0, len, alloc_len = array->alloc_len; char *alloc = array->array, *tmp; - while ((len = read(fd, vmon->buf, sizeof(vmon->buf))) > 0) { + while ((len = pread(fd, vmon->buf, sizeof(vmon->buf), total)) > 0) { if (total + len > alloc_len) { /* realloc to accomodate the new total */ tmp = realloc(alloc, total + len); @@ -263,7 +251,7 @@ typedef enum _vmon_proc_stat_fsm_t { static sample_ret_t proc_sample_stat(vmon_t *vmon, vmon_proc_t *proc, vmon_proc_stat_t **store) { int changes = 0; - int i, len; + int i, len, total = 0; char *arg; int argn, prev_argc; vmon_proc_stat_fsm_t state = VMON_PARSER_STATE_PROC_STAT_PID; @@ -302,11 +290,6 @@ _retry: /* initially everything is considered changed */ memset((*store)->changed, 0xff, sizeof((*store)->changed)); } else { - try_lseek((*store)->comm_fd, 0, SEEK_SET); - try_lseek((*store)->cmdline_fd, 0, SEEK_SET); - try_lseek((*store)->wchan_fd, 0, SEEK_SET); - try_lseek((*store)->stat_fd, 0, SEEK_SET); - /* clear the entire changed bitmap */ memset((*store)->changed, 0, sizeof((*store)->changed)); } @@ -348,7 +331,9 @@ _retry: * scenario and retry the sample when detected by goto _retry */ /* read in stat and parse it assigning the stat members accordingly */ - while ((len = try_read((*store)->stat_fd, vmon->buf, sizeof(vmon->buf))) > 0) { + while ((len = try_pread((*store)->stat_fd, vmon->buf, sizeof(vmon->buf), total)) > 0) { + total += len; + for (i = 0; i < len; i++) { /* parse the fields from the file, stepping through... */ input = vmon->buf[i]; @@ -372,7 +357,7 @@ _out: static int proc_follow_children(vmon_t *vmon, vmon_proc_t *proc, vmon_proc_follow_children_t **store) { int changes = 0; - int len, i, child_pid = 0, found; + int len, total = 0, i, child_pid = 0, found; vmon_proc_t *tmp, *_tmp; list_head_t *cur, *start; @@ -389,8 +374,6 @@ static int proc_follow_children(vmon_t *vmon, vmon_proc_t *proc, vmon_proc_follo *store = calloc(1, sizeof(vmon_proc_follow_children_t)); (*store)->children_fd = openf(vmon, O_RDONLY, vmon->proc_dir, "%i/task/%i/children", proc->pid, proc->pid); - } else { - try_lseek((*store)->children_fd, 0, SEEK_SET); } /* unmonitor stale children on entry, this concludes the two-phase removal of a process */ @@ -414,7 +397,9 @@ static int proc_follow_children(vmon_t *vmon, vmon_proc_t *proc, vmon_proc_follo /* maintain our awareness of children, if we detect a new child initiate monitoring for it, existing children get their generation number updated */ start = &proc->children; - while ((len = try_read((*store)->children_fd, vmon->buf, sizeof(vmon->buf))) > 0) { + while ((len = try_pread((*store)->children_fd, vmon->buf, sizeof(vmon->buf), total)) > 0) { + total += len; + for (i = 0; i < len; i++) { switch (vmon->buf[i]) { case '0' ... '9': @@ -795,7 +780,7 @@ typedef enum _vmon_proc_vm_fsm_t { static sample_ret_t proc_sample_vm(vmon_t *vmon, vmon_proc_t *proc, vmon_proc_vm_t **store) { - int i, len; + int i, len, total = 0; int changes = 0; vmon_proc_vm_fsm_t state = VMON_PARSER_STATE_PROC_VM_SIZE_PAGES; #define VMON_PREPARE_PARSER @@ -818,14 +803,14 @@ static sample_ret_t proc_sample_vm(vmon_t *vmon, vmon_proc_t *proc, vmon_proc_vm /* initially everything is considered changed */ memset((*store)->changed, 0xff, sizeof((*store)->changed)); } else { - try_lseek((*store)->statm_fd, 0, SEEK_SET); - /* clear the entire changed bitmap */ memset((*store)->changed, 0, sizeof((*store)->changed)); } /* read in statm and parse it assigning the vm members accordingly */ - while ((len = try_read((*store)->statm_fd, vmon->buf, sizeof(vmon->buf))) > 0) { + while ((len = try_pread((*store)->statm_fd, vmon->buf, sizeof(vmon->buf), total)) > 0) { + total += len; + for (i = 0; i < len; i++) { /* parse the fields from the file, stepping through... */ input = vmon->buf[i]; @@ -852,7 +837,7 @@ typedef enum _vmon_proc_io_fsm_t { static sample_ret_t proc_sample_io(vmon_t *vmon, vmon_proc_t *proc, vmon_proc_io_t **store) { - int i, len; + int i, len, total = 0; int changes = 0; vmon_proc_io_fsm_t state = VMON_PARSER_STATE_PROC_IO_RCHAR_LABEL; #define VMON_PREPARE_PARSER @@ -875,14 +860,14 @@ static sample_ret_t proc_sample_io(vmon_t *vmon, vmon_proc_t *proc, vmon_proc_io /* initially everything is considered changed */ memset((*store)->changed, 0xff, sizeof((*store)->changed)); } else { - try_lseek((*store)->io_fd, 0, SEEK_SET); - /* clear the entire changed bitmap */ memset((*store)->changed, 0, sizeof((*store)->changed)); } /* read in io and parse it assigning the io members accordingly */ - while ((len = try_read((*store)->io_fd, vmon->buf, sizeof(vmon->buf))) > 0) { + while ((len = try_pread((*store)->io_fd, vmon->buf, sizeof(vmon->buf), total)) > 0) { + total += len; + for (i = 0; i < len; i++) { /* parse the fields from the file, stepping through... */ input = vmon->buf[i]; @@ -911,7 +896,7 @@ typedef enum _vmon_sys_stat_fsm_t { /* system-wide stat sampling, things like CPU usages, stuff in /proc/stat */ static sample_ret_t sys_sample_stat(vmon_t *vmon, vmon_sys_stat_t **store) { - int i, len; + int i, len, total = 0; int changes = 0; vmon_sys_stat_fsm_t state = VMON_PARSER_STATE_SYS_STAT_CPU_PREFIX; /* this could be defined as the "VMON_PARSER_INITIAL_STATE" */ #define VMON_PREPARE_PARSER @@ -925,11 +910,11 @@ static sample_ret_t sys_sample_stat(vmon_t *vmon, vmon_sys_stat_t **store) if (!(*store)) { /* ctor */ (*store) = calloc(1, sizeof(vmon_sys_stat_t)); (*store)->stat_fd = openat(dirfd(vmon->proc_dir), "stat", O_RDONLY); - } else { - try_lseek((*store)->stat_fd, 0, SEEK_SET); } - while ((len = try_read((*store)->stat_fd, vmon->buf, sizeof(vmon->buf))) > 0) { + while ((len = try_pread((*store)->stat_fd, vmon->buf, sizeof(vmon->buf), total)) > 0) { + total += len; + for (i = 0; i < len; i++) { input = vmon->buf[i]; switch (state) { @@ -956,7 +941,7 @@ typedef enum _vmon_sys_vm_fsm_t { static sample_ret_t sys_sample_vm(vmon_t *vmon, vmon_sys_vm_t **store) { - int i, len; + int i, len, total = 0; int changes = 0; vmon_sys_vm_fsm_t state = VMON_PARSER_STATE_SYS_VM_TOTAL_KB_LABEL; /* this could be defined as the "VMON_PARSER_INITIAL_STATE" */ #define VMON_PREPARE_PARSER @@ -974,11 +959,12 @@ static sample_ret_t sys_sample_vm(vmon_t *vmon, vmon_sys_vm_t **store) /* initially everything is considered changed */ memset((*store)->changed, 0xff, sizeof((*store)->changed)); } else { - try_lseek((*store)->meminfo_fd, 0, SEEK_SET); memset((*store)->changed, 0, sizeof((*store)->changed)); } - while ((len = try_read((*store)->meminfo_fd, vmon->buf, sizeof(vmon->buf))) > 0) { + while ((len = try_pread((*store)->meminfo_fd, vmon->buf, sizeof(vmon->buf), total)) > 0) { + total += len; + for (i = 0; i < len; i++) { input = vmon->buf[i]; switch (state) { |