trace_processor: add support for importing ctrace files
This adds a GZIP parser as ctrace is just systrace compressed with
deflate and the TRACE: header added.
This parser just forwards to the systrace parser after decompression.
Change-Id: I8a0118f7ff8c083f7e6f3bed1eda7de36ea701dc
diff --git a/Android.bp b/Android.bp
index 71646b3..23f38db 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3545,6 +3545,7 @@
"src/trace_processor/fuchsia_trace_parser.cc",
"src/trace_processor/fuchsia_trace_tokenizer.cc",
"src/trace_processor/fuchsia_trace_utils.cc",
+ "src/trace_processor/gzip_trace_parser.cc",
"src/trace_processor/heap_profile_allocation_table.cc",
"src/trace_processor/heap_profile_callsite_table.cc",
"src/trace_processor/heap_profile_frame_table.cc",
@@ -3595,6 +3596,7 @@
"liblog",
"libprotobuf-cpp-full",
"libprotobuf-cpp-lite",
+ "libz",
],
static_libs: [
"libsqlite",
@@ -3641,7 +3643,10 @@
cflags: [
"-DGOOGLE_PROTOBUF_NO_RTTI",
"-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ "-DHAVE_HIDDEN",
"-DPERFETTO_BUILD_WITH_ANDROID",
+ "-DUSE_MMAP",
+ "-DZLIB_CONST",
],
}
diff --git a/BUILD b/BUILD
index 3a624d7..bc1aea2 100644
--- a/BUILD
+++ b/BUILD
@@ -171,6 +171,8 @@
"src/trace_processor/fuchsia_trace_tokenizer.h",
"src/trace_processor/fuchsia_trace_utils.cc",
"src/trace_processor/fuchsia_trace_utils.h",
+ "src/trace_processor/gzip_trace_parser.cc",
+ "src/trace_processor/gzip_trace_parser.h",
"src/trace_processor/heap_profile_allocation_table.cc",
"src/trace_processor/heap_profile_allocation_table.h",
"src/trace_processor/heap_profile_callsite_table.cc",
@@ -342,6 +344,7 @@
"//third_party/perfetto/protos:trace_zero_cc_proto",
"//third_party/sqlite",
"//third_party/sqlite:sqlite_ext_percentile",
+ "//third_party/zlib",
],
)
@@ -448,6 +451,8 @@
"src/trace_processor/fuchsia_trace_tokenizer.h",
"src/trace_processor/fuchsia_trace_utils.cc",
"src/trace_processor/fuchsia_trace_utils.h",
+ "src/trace_processor/gzip_trace_parser.cc",
+ "src/trace_processor/gzip_trace_parser.h",
"src/trace_processor/heap_profile_allocation_table.cc",
"src/trace_processor/heap_profile_allocation_table.h",
"src/trace_processor/heap_profile_callsite_table.cc",
@@ -575,6 +580,7 @@
"//third_party/protobuf:libprotoc",
"//third_party/sqlite",
"//third_party/sqlite:sqlite_ext_percentile",
+ "//third_party/zlib",
],
)
@@ -681,6 +687,8 @@
"src/trace_processor/fuchsia_trace_tokenizer.h",
"src/trace_processor/fuchsia_trace_utils.cc",
"src/trace_processor/fuchsia_trace_utils.h",
+ "src/trace_processor/gzip_trace_parser.cc",
+ "src/trace_processor/gzip_trace_parser.h",
"src/trace_processor/heap_profile_allocation_table.cc",
"src/trace_processor/heap_profile_allocation_table.h",
"src/trace_processor/heap_profile_callsite_table.cc",
@@ -833,6 +841,7 @@
"//third_party/protobuf:libprotoc",
"//third_party/sqlite",
"//third_party/sqlite:sqlite_ext_percentile",
+ "//third_party/zlib",
],
)
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 8950cee..bd8c3e4 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -75,6 +75,8 @@
"fuchsia_trace_tokenizer.h",
"fuchsia_trace_utils.cc",
"fuchsia_trace_utils.h",
+ "gzip_trace_parser.cc",
+ "gzip_trace_parser.h",
"heap_profile_allocation_table.cc",
"heap_profile_allocation_table.h",
"heap_profile_callsite_table.cc",
@@ -165,6 +167,7 @@
deps = [
":sqlite",
+ "../../buildtools:zlib",
"../../gn:default_deps",
"../../include/perfetto/ext/traced:sys_stats_counters",
"../../protos/perfetto/common:zero",
diff --git a/src/trace_processor/gzip_trace_parser.cc b/src/trace_processor/gzip_trace_parser.cc
new file mode 100644
index 0000000..39f407d
--- /dev/null
+++ b/src/trace_processor/gzip_trace_parser.cc
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/gzip_trace_parser.h"
+
+#include <zlib.h>
+
+#include "src/trace_processor/systrace_trace_parser.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+GzipTraceParser::GzipTraceParser(TraceProcessorContext* context)
+ : context_(context), z_stream_(new z_stream()) {
+ z_stream_->zalloc = Z_NULL;
+ z_stream_->zfree = Z_NULL;
+ z_stream_->opaque = Z_NULL;
+ inflateInit(z_stream_.get());
+}
+
+GzipTraceParser::~GzipTraceParser() = default;
+
+util::Status GzipTraceParser::Parse(std::unique_ptr<uint8_t[]> data,
+ size_t size) {
+ uint8_t* start = data.get();
+ size_t len = size;
+
+ static const char kSystraceFilerHeader[] = "TRACE:\n";
+ if (!inner_) {
+ inner_.reset(new SystraceTraceParser(context_));
+
+ // Strip the header by ignoring the associated bytes.
+ start += strlen(kSystraceFilerHeader);
+ len -= strlen(kSystraceFilerHeader);
+ }
+
+ z_stream_->next_in = start;
+ z_stream_->avail_in = static_cast<uInt>(len);
+
+ // Our default uncompressed buffer size is 32MB as it allows for good
+ // throughput.
+ constexpr size_t kUncompressedBufferSize = 32 * 1024 * 1024;
+ int ret = Z_OK;
+ for (; ret != Z_STREAM_END && z_stream_->avail_in != 0;) {
+ std::unique_ptr<uint8_t[]> buffer(new uint8_t[kUncompressedBufferSize]);
+ z_stream_->next_out = buffer.get();
+ z_stream_->avail_out = static_cast<uInt>(kUncompressedBufferSize);
+
+ ret = inflate(z_stream_.get(), Z_NO_FLUSH);
+ switch (ret) {
+ case Z_NEED_DICT:
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ // Ignore inflateEnd error as we will error out anyway.
+ inflateEnd(z_stream_.get());
+ return util::ErrStatus("Error decompressing ctrace file");
+ }
+
+ size_t read = size * 64 - z_stream_->avail_out;
+ util::Status status = inner_->Parse(std::move(buffer), read);
+ if (!status.ok())
+ return status;
+ }
+ if (ret == Z_STREAM_END) {
+ ret = inflateEnd(z_stream_.get());
+ if (ret == Z_STREAM_ERROR)
+ return util::ErrStatus("Error finishing decompression");
+ }
+ return util::OkStatus();
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/gzip_trace_parser.h b/src/trace_processor/gzip_trace_parser.h
new file mode 100644
index 0000000..a129c4b
--- /dev/null
+++ b/src/trace_processor/gzip_trace_parser.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_GZIP_TRACE_PARSER_H_
+#define SRC_TRACE_PROCESSOR_GZIP_TRACE_PARSER_H_
+
+#include "src/trace_processor/chunked_trace_reader.h"
+
+struct z_stream_s;
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+class GzipTraceParser : public ChunkedTraceReader {
+ public:
+ explicit GzipTraceParser(TraceProcessorContext*);
+ ~GzipTraceParser() override;
+
+ // ChunkedTraceReader implementation
+ util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
+
+ private:
+ TraceProcessorContext* const context_;
+ std::unique_ptr<z_stream_s> z_stream_;
+ std::unique_ptr<ChunkedTraceReader> inner_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_GZIP_TRACE_PARSER_H_
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 9e34dd3..f6d657d 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -35,6 +35,7 @@
#include "src/trace_processor/event_tracker.h"
#include "src/trace_processor/fuchsia_trace_parser.h"
#include "src/trace_processor/fuchsia_trace_tokenizer.h"
+#include "src/trace_processor/gzip_trace_parser.h"
#include "src/trace_processor/heap_profile_allocation_table.h"
#include "src/trace_processor/heap_profile_callsite_table.h"
#include "src/trace_processor/heap_profile_frame_table.h"
@@ -294,6 +295,10 @@
if (base::StartsWith(start, " "))
return kSystraceTraceType;
+ // Ctrace is GZIPed systrace with no headers.
+ if (base::StartsWith(start, "TRACE:"))
+ return kCtraceTraceType;
+
return kProtoTraceType;
}
@@ -400,6 +405,9 @@
case kSystraceTraceType:
context_.chunk_reader.reset(new SystraceTraceParser(&context_));
break;
+ case kCtraceTraceType:
+ context_.chunk_reader.reset(new GzipTraceParser(&context_));
+ break;
case kUnknownTraceType:
return util::ErrStatus("Unknown trace type provided");
}
diff --git a/src/trace_processor/trace_processor_impl.h b/src/trace_processor/trace_processor_impl.h
index 8673928..e9c3435 100644
--- a/src/trace_processor/trace_processor_impl.h
+++ b/src/trace_processor/trace_processor_impl.h
@@ -42,6 +42,7 @@
kJsonTraceType,
kFuchsiaTraceType,
kSystraceTraceType,
+ kCtraceTraceType,
};
TraceType GuessTraceType(const uint8_t* data, size_t size);
diff --git a/tools/gen_bazel b/tools/gen_bazel
index c430fbe..032a78b 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -103,6 +103,10 @@
module.deps.add(Label('//third_party/perfetto/google:perfetto_version'))
+def enable_zlib(module):
+ module.deps.add(Label('//third_party/zlib'))
+
+
def disable_module(module):
pass
@@ -116,6 +120,7 @@
'//buildtools:protobuf_full': enable_protobuf_full,
'//buildtools:protoc': disable_module,
'//buildtools:sqlite': enable_sqlite,
+ '//buildtools:zlib': enable_zlib,
'//gn:default_deps': disable_module,
'//gn:protoc_lib_deps': enable_protobuf_full,
'//gn/standalone:gen_git_revision': enable_perfetto_version,