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
diff --git a/atrace/Android.mk b/atrace/Android.mk
index c1a0d87..df79e82 100644
--- a/atrace/Android.mk
+++ b/atrace/Android.mk
@@ -5,8 +5,12 @@
LOCAL_SRC_FILES:= atrace.c
+LOCAL_C_INCLUDES += external/zlib
+
LOCAL_MODULE:= atrace
LOCAL_MODULE_TAGS:= debug
+LOCAL_STATIC_LIBRARIES := libz
+
include $(BUILD_EXECUTABLE)
diff --git a/atrace/atrace.c b/atrace/atrace.c
index 92fe5d1..7b4f55e 100644
--- a/atrace/atrace.c
+++ b/atrace/atrace.c
@@ -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_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 @@
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 @@
" -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 @@
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 @@
g_traceWorkqueue = true;
break;
+ case 'z':
+ g_compress = true;
+ break;
+
default:
fprintf(stderr, "\n");
showHelp(argv[0]);