Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b5170b2 authored by Jamie Gennis's avatar Jamie Gennis
Browse files

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
parent fe312b98
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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)
+91 −7
Original line number Diff line number Diff line
@@ -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,12 +231,89 @@ static void dumpTrace()
        return;
    }

    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]);