From 4afadab95824e12b551276d2fbf91199082d6df9 Mon Sep 17 00:00:00 2001 From: Jonas Haag Date: Mon, 13 Jun 2016 21:34:21 +0200 Subject: [PATCH 1/2] Prototype: use separate process for gzip --- src/vmprof_common.h | 48 +++++++++++++++++++++++++++++++++++++++++---- src/vmprof_main.h | 9 ++++++++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/vmprof_common.h b/src/vmprof_common.h index 38c3a6a3..c2d24149 100644 --- a/src/vmprof_common.h +++ b/src/vmprof_common.h @@ -11,6 +11,8 @@ static int opened_profile(char *interp_name, int memory); static struct profbuf_s *volatile current_codes; #endif +#define ENABLE_GZIP (defined(__unix__) || defined(__APPLE__)) + #define MAX_STACK_DEPTH \ ((SINGLE_BUF_SIZE - sizeof(struct prof_stacktrace_s)) / sizeof(void *)) @@ -32,6 +34,34 @@ typedef struct prof_stacktrace_s { void *stack[]; } prof_stacktrace_s; +#if ENABLE_GZIP +#include "tinygzip.c" +static int pipe_gzip(int fd) +{ + int pipefds[2]; + + if (pipe(pipefds) == -1) + return -1; + + pid_t pid = fork(); + switch (pid) { + case -1: + close(pipefds[0]); + close(pipefds[1]); + return -1; + case 0: + close(pipefds[1]); + if (tinygz(pipefds[0], fd)) { + perror("gzip"); + exit(1); + } + exit(0); + default: + close(pipefds[0]); + return pipefds[1]; + } +} +#endif RPY_EXTERN char *vmprof_init(int fd, double interval, int memory, char *interp_name) @@ -50,13 +80,23 @@ char *vmprof_init(int fd, double interval, int memory, char *interp_name) if (memory) return "memory tracking not supported on non-linux"; #endif + assert(fd >= 0); +#if ENABLE_GZIP + int gzfd = pipe_gzip(fd); + if (gzfd < 0) + goto err; + profile_file = gzfd; +#else profile_file = fd; - if (opened_profile(interp_name, memory) < 0) { - profile_file = -1; - return strerror(errno); - } +#endif + if (opened_profile(interp_name, memory) < 0) + goto err; return NULL; + +err: + profile_file = -1; + return strerror(errno); } static int read_trace_from_cpy_frame(PyFrameObject *frame, void **result, int max_depth) diff --git a/src/vmprof_main.h b/src/vmprof_main.h index e0f0a69b..c6e13cab 100644 --- a/src/vmprof_main.h +++ b/src/vmprof_main.h @@ -345,8 +345,15 @@ static int close_profile(void) close(proc_file); proc_file = -1; - /* don't close() the file descriptor from here */ + +#if ENABLE_GZIP + /* This doesn't close() the original file descriptor */ + close(profile_file); +#else + /* Don't close() the original file descriptor from here */ +#endif profile_file = -1; + return 0; } From acb9e521770f9dd4355bc3a23bbe8bfc079d7855 Mon Sep 17 00:00:00 2001 From: Jonas Haag Date: Mon, 13 Jun 2016 21:37:30 +0200 Subject: [PATCH 2/2] Forgot this file --- src/tinygzip.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/tinygzip.c diff --git a/src/tinygzip.c b/src/tinygzip.c new file mode 100644 index 00000000..0ff01597 --- /dev/null +++ b/src/tinygzip.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include + +#define READ_BUFFER_SIZE 64*1024 + +static int tinygz(int in_fd, int out_fd); + + +int main(int argc, char *argv[]) { + int out_fd = atoi(argv[1]); + return tinygz(STDIN_FILENO, out_fd); +} + + +static int tinygz(int in_fd, int out_fd) { + gzFile gz = gzdopen(out_fd, "ab4"); + if (gz == NULL) + goto err; + + char read_buf[READ_BUFFER_SIZE]; + + for (;;) { + ssize_t bytes_read = read(in_fd, read_buf, READ_BUFFER_SIZE); + if (bytes_read == 0) { + goto done; + } else if (bytes_read < 0) { + if (errno == EAGAIN) { + continue; + } else { + perror("read()"); + goto err; + } + } else { + size_t bytes_written; + while (bytes_read > 0) { + bytes_written = gzwrite(gz, read_buf, bytes_read); + if (bytes_written == 0) { + perror("gzwrite()"); + goto err; + } else { + bytes_read -= bytes_written; + } + } + } + } + + assert(0 && "unreachable"); + +done: + return gzclose_w(gz) == Z_OK ? 0 : 1; + +err: + if (gz != NULL) + gzclose_w(gz); + return 1; +}