trace_processor: Add slices from ftrace traces - Refactor slice tracking code from json_trace_parser into slice_tracker. - Introduce Print parsing code in proto_trace_parser. - Add tests for slice tracking code. Change-Id: Iec14860f45e1eb36a884ef1ddd91ba35d2e91132
diff --git a/src/trace_processor/json_trace_parser.cc b/src/trace_processor/json_trace_parser.cc index 81e419c..e7a8002 100644 --- a/src/trace_processor/json_trace_parser.cc +++ b/src/trace_processor/json_trace_parser.cc
@@ -26,6 +26,7 @@ #include "perfetto/base/logging.h" #include "perfetto/base/utils.h" #include "src/trace_processor/process_tracker.h" +#include "src/trace_processor/slice_tracker.h" #include "src/trace_processor/trace_processor_context.h" #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) || \ @@ -106,7 +107,7 @@ ProcessTracker* procs = context_->process_tracker.get(); TraceStorage* storage = context_->storage.get(); - TraceStorage::NestableSlices* slices = storage->mutable_nestable_slices(); + SliceTracker* slice_tracker = context_->slice_tracker.get(); while (next < end) { Json::Value value; @@ -127,42 +128,19 @@ StringId cat_id = storage->InternString(cat); StringId name_id = storage->InternString(name); UniqueTid utid = procs->UpdateThread(tid, pid); - SlicesStack& stack = threads_[utid]; - - auto add_slice = [slices, &stack, utid, cat_id, - name_id](const Slice& slice) { - if (stack.size() >= std::numeric_limits<uint8_t>::max()) - return; - const uint8_t depth = static_cast<uint8_t>(stack.size()) - 1; - uint64_t parent_stack_id, stack_id; - std::tie(parent_stack_id, stack_id) = GetStackHashes(stack); - slices->AddSlice(slice.start_ts, slice.end_ts - slice.start_ts, utid, - cat_id, name_id, depth, stack_id, parent_stack_id); - }; switch (phase) { case 'B': { // TRACE_EVENT_BEGIN. - MaybeCloseStack(ts, stack); - stack.emplace_back(Slice{cat_id, name_id, ts, 0}); + slice_tracker->Begin(ts, utid, cat_id, name_id); break; } case 'E': { // TRACE_EVENT_END. - PERFETTO_CHECK(!stack.empty()); - MaybeCloseStack(ts, stack); - PERFETTO_CHECK(stack.back().cat_id == cat_id); - PERFETTO_CHECK(stack.back().name_id == name_id); - Slice& slice = stack.back(); - slice.end_ts = slice.start_ts; - add_slice(slice); - stack.pop_back(); + slice_tracker->End(ts, utid, cat_id, name_id); break; } case 'X': { // TRACE_EVENT (scoped event). - MaybeCloseStack(ts, stack); - uint64_t end_ts = ts + value["dur"].asUInt() * 1000; - stack.emplace_back(Slice{cat_id, name_id, ts, end_ts}); - Slice& slice = stack.back(); - add_slice(slice); + uint64_t duration = value["dur"].asUInt() * 1000; + slice_tracker->Scoped(ts, utid, cat_id, name_id, duration); break; } case 'M': { // Metadata events (process and thread names). @@ -178,54 +156,11 @@ } } } - // TODO(primiano): auto-close B slices left open at the end. } offset_ += static_cast<uint64_t>(next - buf); buffer_.erase(buffer_.begin(), buffer_.begin() + (next - buf)); return true; } -void JsonTraceParser::MaybeCloseStack(uint64_t ts, SlicesStack& stack) { - bool check_only = false; - for (int i = static_cast<int>(stack.size()) - 1; i >= 0; i--) { - const Slice& slice = stack[size_t(i)]; - if (slice.end_ts == 0) { - check_only = true; - } - - if (check_only) { - PERFETTO_DCHECK(ts >= slice.start_ts); - PERFETTO_DCHECK(slice.end_ts == 0 || ts <= slice.end_ts); - continue; - } - - if (slice.end_ts <= ts) { - stack.pop_back(); - } - } -} - -// Returns <parent_stack_id, stack_id>, where -// |parent_stack_id| == hash(stack_id - last slice). -std::tuple<uint64_t, uint64_t> JsonTraceParser::GetStackHashes( - const SlicesStack& stack) { - PERFETTO_DCHECK(!stack.empty()); - std::string s; - s.reserve(stack.size() * sizeof(uint64_t) * 2); - constexpr uint64_t kMask = uint64_t(-1) >> 1; - uint64_t parent_stack_id = 0; - for (size_t i = 0; i < stack.size(); i++) { - if (i == stack.size() - 1) - parent_stack_id = i > 0 ? (std::hash<std::string>{}(s)) & kMask : 0; - const Slice& slice = stack[i]; - s.append(reinterpret_cast<const char*>(&slice.cat_id), - sizeof(slice.cat_id)); - s.append(reinterpret_cast<const char*>(&slice.name_id), - sizeof(slice.name_id)); - } - uint64_t stack_id = (std::hash<std::string>{}(s)) & kMask; - return std::make_tuple(parent_stack_id, stack_id); -} - } // namespace trace_processor } // namespace perfetto