Loading tools/aapt2/trace/TraceBuffer.cpp +75 −53 Original line number Diff line number Diff line Loading @@ -36,13 +36,14 @@ constexpr char kBegin = 'B'; constexpr char kEnd = 'E'; struct TracePoint { char type; pid_t tid; int64_t time; std::string tag; char type; }; std::vector<TracePoint> traces; bool enabled = true; int64_t GetTime() noexcept { auto now = std::chrono::steady_clock::now(); Loading @@ -51,34 +52,39 @@ int64_t GetTime() noexcept { } // namespace anonymous void AddWithTime(const std::string& tag, char type, int64_t time) noexcept { TracePoint t = {getpid(), time, tag, type}; traces.emplace_back(t); void AddWithTime(std::string tag, char type, int64_t time) noexcept { TracePoint t = {type, getpid(), time, std::move(tag)}; traces.emplace_back(std::move(t)); } void Add(const std::string& tag, char type) noexcept { AddWithTime(tag, type, GetTime()); void Add(std::string tag, char type) noexcept { AddWithTime(std::move(tag), type, GetTime()); } void Flush(const std::string& basePath) { TRACE_CALL(); if (basePath.empty()) { return; } BeginTrace(__func__); // We can't do much here, only record that it happened. std::stringstream s; std::ostringstream s; s << basePath << aapt::file::sDirSep << "report_aapt2_" << getpid() << ".json"; FILE* f = android::base::utf8::fopen(s.str().c_str(), "a"); if (f == nullptr) { return; } // Wrap the trace in a JSON array [] to make Chrome/Perfetto UI handle it. char delimiter = '['; for(const TracePoint& trace : traces) { fprintf(f, "{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", " "\"name\" : \"%s\" },\n", trace.time, trace.type, 0, trace.tid, trace.tag.c_str()); fprintf(f, "%c{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", \"name\" : \"%s\" }\n", delimiter, trace.time, trace.type, 0, trace.tid, trace.tag.c_str()); delimiter = ','; } if (!traces.empty()) { fprintf(f, "]"); } fclose(f); traces.clear(); Loading @@ -86,66 +92,82 @@ void Flush(const std::string& basePath) { } // namespace tracebuffer void BeginTrace(const std::string& tag) { tracebuffer::Add(tag, tracebuffer::kBegin); void BeginTrace(std::string tag) { if (!tracebuffer::enabled) return; tracebuffer::Add(std::move(tag), tracebuffer::kBegin); } void EndTrace(std::string tag) { if (!tracebuffer::enabled) return; tracebuffer::Add(std::move(tag), tracebuffer::kEnd); } bool Trace::enable(bool value) { return tracebuffer::enabled = value; } void EndTrace() { tracebuffer::Add("", tracebuffer::kEnd); Trace::Trace(const char* tag) { if (!tracebuffer::enabled) return; tag_.assign(tag); tracebuffer::Add(tag_, tracebuffer::kBegin); } Trace::Trace(const std::string& tag) { tracebuffer::Add(tag, tracebuffer::kBegin); Trace::Trace(std::string tag) : tag_(std::move(tag)) { if (!tracebuffer::enabled) return; tracebuffer::Add(tag_, tracebuffer::kBegin); } Trace::Trace(const std::string& tag, const std::vector<android::StringPiece>& args) { std::stringstream s; template <class SpanOfStrings> std::string makeTag(std::string_view tag, const SpanOfStrings& args) { std::ostringstream s; s << tag; s << " "; for (auto& arg : args) { if (!args.empty()) { for (const auto& arg : args) { s << ' '; s << arg; s << " "; } tracebuffer::Add(s.str(), tracebuffer::kBegin); } Trace::~Trace() { tracebuffer::Add("", tracebuffer::kEnd); return std::move(s).str(); } FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag) : basepath_(basepath) { tracebuffer::Add(tag, tracebuffer::kBegin); Trace::Trace(std::string_view tag, const std::vector<android::StringPiece>& args) { if (!tracebuffer::enabled) return; tag_ = makeTag(tag, args); tracebuffer::Add(tag_, tracebuffer::kBegin); } FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag, const std::vector<android::StringPiece>& args) : basepath_(basepath) { std::stringstream s; s << tag; s << " "; for (auto& arg : args) { s << arg; s << " "; Trace::~Trace() { if (!tracebuffer::enabled) return; tracebuffer::Add(std::move(tag_), tracebuffer::kEnd); } tracebuffer::Add(s.str(), tracebuffer::kBegin); FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag) { if (!Trace::enable(!basepath.empty())) return; basepath_.assign(basepath); tag_.assign(tag); tracebuffer::Add(tag_, tracebuffer::kBegin); } FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag, const std::vector<std::string>& args) : basepath_(basepath){ std::stringstream s; s << tag; s << " "; for (auto& arg : args) { s << arg; s << " "; FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag, const std::vector<android::StringPiece>& args) { if (!Trace::enable(!basepath.empty())) return; basepath_.assign(basepath); tag_ = makeTag(tag, args); tracebuffer::Add(tag_, tracebuffer::kBegin); } tracebuffer::Add(s.str(), tracebuffer::kBegin); FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag, const std::vector<std::string>& args) { if (!Trace::enable(!basepath.empty())) return; basepath_.assign(basepath); tag_ = makeTag(tag, args); tracebuffer::Add(tag_, tracebuffer::kBegin); } FlushTrace::~FlushTrace() { tracebuffer::Add("", tracebuffer::kEnd); if (!tracebuffer::enabled) return; tracebuffer::Add(tag_, tracebuffer::kEnd); tracebuffer::Flush(basepath_); } } // namespace aapt tools/aapt2/trace/TraceBuffer.h +23 −14 Original line number Diff line number Diff line Loading @@ -17,41 +17,50 @@ #ifndef AAPT_TRACEBUFFER_H #define AAPT_TRACEBUFFER_H #include <androidfw/StringPiece.h> #include <string> #include <string_view> #include <vector> #include <androidfw/StringPiece.h> namespace aapt { // Record timestamps for beginning and end of a task and generate systrace json fragments. // This is an in-process ftrace which has the advantage of being platform independent. // These methods are NOT thread-safe since aapt2 is not multi-threaded. // Convenience RIAA object to automatically finish an event when object goes out of scope. // Convenience RAII object to automatically finish an event when object goes out of scope. class Trace { public: Trace(const std::string& tag); Trace(const std::string& tag, const std::vector<android::StringPiece>& args); Trace(const char* tag); Trace(std::string tag); Trace(std::string_view tag, const std::vector<android::StringPiece>& args); ~Trace(); static bool enable(bool value = true); private: std::string tag_; }; // Manual markers. void BeginTrace(const std::string& tag); void EndTrace(); void BeginTrace(std::string tag); void EndTrace(std::string tag); // A main trace is required to flush events to disk. Events are formatted in systrace // json format. class FlushTrace { public: explicit FlushTrace(const std::string& basepath, const std::string& tag); explicit FlushTrace(const std::string& basepath, const std::string& tag, explicit FlushTrace(std::string_view basepath, std::string_view tag); explicit FlushTrace(std::string_view basepath, std::string_view tag, const std::vector<android::StringPiece>& args); explicit FlushTrace(const std::string& basepath, const std::string& tag, explicit FlushTrace(std::string_view basepath, std::string_view tag, const std::vector<std::string>& args); ~FlushTrace(); private: std::string basepath_; std::string tag_; }; #define TRACE_CALL() Trace __t(__func__) Loading Loading
tools/aapt2/trace/TraceBuffer.cpp +75 −53 Original line number Diff line number Diff line Loading @@ -36,13 +36,14 @@ constexpr char kBegin = 'B'; constexpr char kEnd = 'E'; struct TracePoint { char type; pid_t tid; int64_t time; std::string tag; char type; }; std::vector<TracePoint> traces; bool enabled = true; int64_t GetTime() noexcept { auto now = std::chrono::steady_clock::now(); Loading @@ -51,34 +52,39 @@ int64_t GetTime() noexcept { } // namespace anonymous void AddWithTime(const std::string& tag, char type, int64_t time) noexcept { TracePoint t = {getpid(), time, tag, type}; traces.emplace_back(t); void AddWithTime(std::string tag, char type, int64_t time) noexcept { TracePoint t = {type, getpid(), time, std::move(tag)}; traces.emplace_back(std::move(t)); } void Add(const std::string& tag, char type) noexcept { AddWithTime(tag, type, GetTime()); void Add(std::string tag, char type) noexcept { AddWithTime(std::move(tag), type, GetTime()); } void Flush(const std::string& basePath) { TRACE_CALL(); if (basePath.empty()) { return; } BeginTrace(__func__); // We can't do much here, only record that it happened. std::stringstream s; std::ostringstream s; s << basePath << aapt::file::sDirSep << "report_aapt2_" << getpid() << ".json"; FILE* f = android::base::utf8::fopen(s.str().c_str(), "a"); if (f == nullptr) { return; } // Wrap the trace in a JSON array [] to make Chrome/Perfetto UI handle it. char delimiter = '['; for(const TracePoint& trace : traces) { fprintf(f, "{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", " "\"name\" : \"%s\" },\n", trace.time, trace.type, 0, trace.tid, trace.tag.c_str()); fprintf(f, "%c{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", \"name\" : \"%s\" }\n", delimiter, trace.time, trace.type, 0, trace.tid, trace.tag.c_str()); delimiter = ','; } if (!traces.empty()) { fprintf(f, "]"); } fclose(f); traces.clear(); Loading @@ -86,66 +92,82 @@ void Flush(const std::string& basePath) { } // namespace tracebuffer void BeginTrace(const std::string& tag) { tracebuffer::Add(tag, tracebuffer::kBegin); void BeginTrace(std::string tag) { if (!tracebuffer::enabled) return; tracebuffer::Add(std::move(tag), tracebuffer::kBegin); } void EndTrace(std::string tag) { if (!tracebuffer::enabled) return; tracebuffer::Add(std::move(tag), tracebuffer::kEnd); } bool Trace::enable(bool value) { return tracebuffer::enabled = value; } void EndTrace() { tracebuffer::Add("", tracebuffer::kEnd); Trace::Trace(const char* tag) { if (!tracebuffer::enabled) return; tag_.assign(tag); tracebuffer::Add(tag_, tracebuffer::kBegin); } Trace::Trace(const std::string& tag) { tracebuffer::Add(tag, tracebuffer::kBegin); Trace::Trace(std::string tag) : tag_(std::move(tag)) { if (!tracebuffer::enabled) return; tracebuffer::Add(tag_, tracebuffer::kBegin); } Trace::Trace(const std::string& tag, const std::vector<android::StringPiece>& args) { std::stringstream s; template <class SpanOfStrings> std::string makeTag(std::string_view tag, const SpanOfStrings& args) { std::ostringstream s; s << tag; s << " "; for (auto& arg : args) { if (!args.empty()) { for (const auto& arg : args) { s << ' '; s << arg; s << " "; } tracebuffer::Add(s.str(), tracebuffer::kBegin); } Trace::~Trace() { tracebuffer::Add("", tracebuffer::kEnd); return std::move(s).str(); } FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag) : basepath_(basepath) { tracebuffer::Add(tag, tracebuffer::kBegin); Trace::Trace(std::string_view tag, const std::vector<android::StringPiece>& args) { if (!tracebuffer::enabled) return; tag_ = makeTag(tag, args); tracebuffer::Add(tag_, tracebuffer::kBegin); } FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag, const std::vector<android::StringPiece>& args) : basepath_(basepath) { std::stringstream s; s << tag; s << " "; for (auto& arg : args) { s << arg; s << " "; Trace::~Trace() { if (!tracebuffer::enabled) return; tracebuffer::Add(std::move(tag_), tracebuffer::kEnd); } tracebuffer::Add(s.str(), tracebuffer::kBegin); FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag) { if (!Trace::enable(!basepath.empty())) return; basepath_.assign(basepath); tag_.assign(tag); tracebuffer::Add(tag_, tracebuffer::kBegin); } FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag, const std::vector<std::string>& args) : basepath_(basepath){ std::stringstream s; s << tag; s << " "; for (auto& arg : args) { s << arg; s << " "; FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag, const std::vector<android::StringPiece>& args) { if (!Trace::enable(!basepath.empty())) return; basepath_.assign(basepath); tag_ = makeTag(tag, args); tracebuffer::Add(tag_, tracebuffer::kBegin); } tracebuffer::Add(s.str(), tracebuffer::kBegin); FlushTrace::FlushTrace(std::string_view basepath, std::string_view tag, const std::vector<std::string>& args) { if (!Trace::enable(!basepath.empty())) return; basepath_.assign(basepath); tag_ = makeTag(tag, args); tracebuffer::Add(tag_, tracebuffer::kBegin); } FlushTrace::~FlushTrace() { tracebuffer::Add("", tracebuffer::kEnd); if (!tracebuffer::enabled) return; tracebuffer::Add(tag_, tracebuffer::kEnd); tracebuffer::Flush(basepath_); } } // namespace aapt
tools/aapt2/trace/TraceBuffer.h +23 −14 Original line number Diff line number Diff line Loading @@ -17,41 +17,50 @@ #ifndef AAPT_TRACEBUFFER_H #define AAPT_TRACEBUFFER_H #include <androidfw/StringPiece.h> #include <string> #include <string_view> #include <vector> #include <androidfw/StringPiece.h> namespace aapt { // Record timestamps for beginning and end of a task and generate systrace json fragments. // This is an in-process ftrace which has the advantage of being platform independent. // These methods are NOT thread-safe since aapt2 is not multi-threaded. // Convenience RIAA object to automatically finish an event when object goes out of scope. // Convenience RAII object to automatically finish an event when object goes out of scope. class Trace { public: Trace(const std::string& tag); Trace(const std::string& tag, const std::vector<android::StringPiece>& args); Trace(const char* tag); Trace(std::string tag); Trace(std::string_view tag, const std::vector<android::StringPiece>& args); ~Trace(); static bool enable(bool value = true); private: std::string tag_; }; // Manual markers. void BeginTrace(const std::string& tag); void EndTrace(); void BeginTrace(std::string tag); void EndTrace(std::string tag); // A main trace is required to flush events to disk. Events are formatted in systrace // json format. class FlushTrace { public: explicit FlushTrace(const std::string& basepath, const std::string& tag); explicit FlushTrace(const std::string& basepath, const std::string& tag, explicit FlushTrace(std::string_view basepath, std::string_view tag); explicit FlushTrace(std::string_view basepath, std::string_view tag, const std::vector<android::StringPiece>& args); explicit FlushTrace(const std::string& basepath, const std::string& tag, explicit FlushTrace(std::string_view basepath, std::string_view tag, const std::vector<std::string>& args); ~FlushTrace(); private: std::string basepath_; std::string tag_; }; #define TRACE_CALL() Trace __t(__func__) Loading