atrace: add support for zlib compression

This change adds the -z command line flag to atrace to enable support for
compressing the trace with zlib as it's printed to stdout.

Change-Id: I45301c63a4d1d388152244fec3c9e05e554598e8
This commit is contained in:
Jamie Gennis 2012-04-28 19:06:49 -07:00
parent fe312b98f7
commit 7b5170b249
2 changed files with 95 additions and 7 deletions

View File

@ -5,8 +5,12 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= atrace.c
LOCAL_C_INCLUDES += external/zlib
LOCAL_MODULE:= atrace
LOCAL_MODULE_TAGS:= debug
LOCAL_STATIC_LIBRARIES := libz
include $(BUILD_EXECUTABLE)

View File

@ -23,6 +23,7 @@
#include <stdlib.h>
#include <sys/sendfile.h>
#include <time.h>
#include <zlib.h>
/* Command line options */
static int g_traceDurationSeconds = 5;
@ -32,6 +33,7 @@ static bool g_traceGovernorLoad = false;
static bool g_traceWorkqueue = false;
static bool g_traceOverwrite = false;
static int g_traceBufferSizeKB = 2048;
static bool g_compress = false;
/* Global state */
static bool g_traceAborted = false;
@ -229,11 +231,88 @@ static void dumpTrace()
return;
}
ssize_t sent = 0;
while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0);
if (sent == -1) {
fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
errno);
if (g_compress) {
z_stream zs;
uint8_t *in, *out;
int result, flush;
bzero(&zs, sizeof(zs));
result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
if (result != Z_OK) {
fprintf(stderr, "error initializing zlib: %d\n", result);
close(traceFD);
return;
}
const size_t bufSize = 64*1024;
in = (uint8_t*)malloc(bufSize);
out = (uint8_t*)malloc(bufSize);
flush = Z_NO_FLUSH;
zs.next_out = out;
zs.avail_out = bufSize;
do {
if (zs.avail_in == 0) {
// More input is needed.
result = read(traceFD, in, bufSize);
if (result < 0) {
fprintf(stderr, "error reading trace: %s (%d)\n",
strerror(errno), errno);
result = Z_STREAM_END;
break;
} else if (result == 0) {
flush = Z_FINISH;
} else {
zs.next_in = in;
zs.avail_in = result;
}
}
if (zs.avail_out == 0) {
// Need to write the output.
result = write(STDOUT_FILENO, out, bufSize);
if ((size_t)result < bufSize) {
fprintf(stderr, "error writing deflated trace: %s (%d)\n",
strerror(errno), errno);
result = Z_STREAM_END; // skip deflate error message
zs.avail_out = bufSize; // skip the final write
break;
}
zs.next_out = out;
zs.avail_out = bufSize;
}
} while ((result = deflate(&zs, flush)) == Z_OK);
if (result != Z_STREAM_END) {
fprintf(stderr, "error deflating trace: %s\n", zs.msg);
}
if (zs.avail_out < bufSize) {
size_t bytes = bufSize - zs.avail_out;
result = write(STDOUT_FILENO, out, bytes);
if ((size_t)result < bytes) {
fprintf(stderr, "error writing deflated trace: %s (%d)\n",
strerror(errno), errno);
}
}
result = deflateEnd(&zs);
if (result != Z_OK) {
fprintf(stderr, "error cleaning up zlib: %d\n", result);
}
free(in);
free(out);
} else {
ssize_t sent = 0;
while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0);
if (sent == -1) {
fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
errno);
}
}
close(traceFD);
@ -250,7 +329,8 @@ static void showHelp(const char *cmd)
" -l trace CPU frequency governor load\n"
" -s trace the kernel scheduler switches\n"
" -t N trace for N seconds [defualt 5]\n"
" -w trace the kernel workqueue\n");
" -w trace the kernel workqueue\n"
" -z compress the trace dump\n");
}
static void handleSignal(int signo) {
@ -283,7 +363,7 @@ int main(int argc, char **argv)
for (;;) {
int ret;
ret = getopt(argc, argv, "b:cflst:w");
ret = getopt(argc, argv, "b:cflst:wz");
if (ret < 0) {
break;
@ -318,6 +398,10 @@ int main(int argc, char **argv)
g_traceWorkqueue = true;
break;
case 'z':
g_compress = true;
break;
default:
fprintf(stderr, "\n");
showHelp(argv[0]);