Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/tinygzip.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
#include <zlib.h>
#include <fcntl.h>
#include <stdio.h>

#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;
}
48 changes: 44 additions & 4 deletions src/vmprof_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply use gzip all the time, and make it an implementation detail of the profile format?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I'm doing in this PR; the flag is only so that you can disable it if zlib is not available on your platform. But if we were to implement the gzip "binary" in Python then there would be no way to disable gzip. (Well, maybe it could be added later if it causes performance problems for someone.)


#define MAX_STACK_DEPTH \
((SINGLE_BUF_SIZE - sizeof(struct prof_stacktrace_s)) / sizeof(void *))

Expand All @@ -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)
Expand All @@ -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)
Expand Down
9 changes: 8 additions & 1 deletion src/vmprof_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down