Merge "ui: delete old flamegraph implementation" into main
diff --git a/Android.bp b/Android.bp
index ee4e0fd..c7412d3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12247,6 +12247,7 @@
"src/trace_processor/importers/common/flow_tracker.cc",
"src/trace_processor/importers/common/global_args_tracker.cc",
"src/trace_processor/importers/common/jit_cache.cc",
+ "src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.cc",
"src/trace_processor/importers/common/machine_tracker.cc",
"src/trace_processor/importers/common/mapping_tracker.cc",
"src/trace_processor/importers/common/metadata_tracker.cc",
diff --git a/BUILD b/BUILD
index 0eb8b6c..2f6503b 100644
--- a/BUILD
+++ b/BUILD
@@ -1536,6 +1536,8 @@
"src/trace_processor/importers/common/global_args_tracker.h",
"src/trace_processor/importers/common/jit_cache.cc",
"src/trace_processor/importers/common/jit_cache.h",
+ "src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.cc",
+ "src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.h",
"src/trace_processor/importers/common/machine_tracker.cc",
"src/trace_processor/importers/common/machine_tracker.h",
"src/trace_processor/importers/common/mapping_tracker.cc",
diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn
index c2f61da..d128b43 100644
--- a/src/trace_processor/importers/common/BUILD.gn
+++ b/src/trace_processor/importers/common/BUILD.gn
@@ -41,6 +41,8 @@
"global_args_tracker.h",
"jit_cache.cc",
"jit_cache.h",
+ "legacy_v8_cpu_profile_tracker.cc",
+ "legacy_v8_cpu_profile_tracker.h",
"machine_tracker.cc",
"machine_tracker.h",
"mapping_tracker.cc",
diff --git a/src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.cc b/src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.cc
new file mode 100644
index 0000000..9206d87
--- /dev/null
+++ b/src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.cc
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2024 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/importers/common/legacy_v8_cpu_profile_tracker.h"
+
+#include <cstdint>
+#include <optional>
+#include <utility>
+
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/flat_hash_map.h"
+#include "perfetto/ext/base/status_or.h"
+#include "perfetto/ext/base/string_view.h"
+#include "src/trace_processor/importers/common/mapping_tracker.h"
+#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/importers/common/stack_profile_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/profiler_tables_py.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto::trace_processor {
+
+LegacyV8CpuProfileTracker::LegacyV8CpuProfileTracker(
+ TraceProcessorContext* context)
+ : context_(context) {}
+
+void LegacyV8CpuProfileTracker::SetStartTsForSessionAndPid(uint64_t session_id,
+ uint32_t pid,
+ int64_t ts) {
+ auto [it, inserted] = state_by_session_and_pid_.Insert(
+ std::make_pair(session_id, pid),
+ State{ts, base::FlatHashMap<uint32_t, CallsiteId>(), nullptr});
+ it->ts = ts;
+ if (inserted) {
+ it->mapping = &context_->mapping_tracker->CreateDummyMapping("");
+ }
+}
+
+base::Status LegacyV8CpuProfileTracker::AddCallsite(
+ uint64_t session_id,
+ uint32_t pid,
+ uint32_t raw_callsite_id,
+ std::optional<uint32_t> parent_raw_callsite_id,
+ base::StringView script_url,
+ base::StringView function_name) {
+ auto* state = state_by_session_and_pid_.Find(std::make_pair(session_id, pid));
+ if (!state) {
+ return base::ErrStatus(
+ "v8 profile id does not exist: cannot insert callsite");
+ }
+ FrameId frame_id =
+ state->mapping->InternDummyFrame(function_name, script_url);
+ CallsiteId callsite_id;
+ if (parent_raw_callsite_id) {
+ auto* parent_id = state->callsites.Find(*parent_raw_callsite_id);
+ if (!parent_id) {
+ return base::ErrStatus(
+ "v8 profile parent id does not exist: cannot insert callsite");
+ }
+ auto row =
+ context_->storage->stack_profile_callsite_table().FindById(*parent_id);
+ callsite_id = context_->stack_profile_tracker->InternCallsite(
+ *parent_id, frame_id, row->depth() + 1);
+ } else {
+ callsite_id = context_->stack_profile_tracker->InternCallsite(std::nullopt,
+ frame_id, 0);
+ }
+ if (!state->callsites.Insert(raw_callsite_id, callsite_id).second) {
+ return base::ErrStatus("v8 profile: callsite with id already exists");
+ }
+ return base::OkStatus();
+}
+
+base::StatusOr<int64_t> LegacyV8CpuProfileTracker::AddDeltaAndGetTs(
+ uint64_t session_id,
+ uint32_t pid,
+ int64_t delta_ts) {
+ auto* state = state_by_session_and_pid_.Find(std::make_pair(session_id, pid));
+ if (!state) {
+ return base::ErrStatus(
+ "v8 profile id does not exist: cannot compute timestamp from delta");
+ }
+ state->ts += delta_ts;
+ return state->ts;
+}
+
+base::Status LegacyV8CpuProfileTracker::AddSample(int64_t ts,
+ uint64_t session_id,
+ uint32_t pid,
+ uint32_t tid,
+ uint32_t raw_callsite_id) {
+ auto* state = state_by_session_and_pid_.Find(std::make_pair(session_id, pid));
+ if (!state) {
+ return base::ErrStatus("v8 callsite id does not exist: cannot add sample");
+ }
+ auto* id = state->callsites.Find(raw_callsite_id);
+ if (!id) {
+ return base::ErrStatus("v8 callsite id does not exist: cannot add sample");
+ }
+ UniqueTid utid = context_->process_tracker->UpdateThread(tid, pid);
+ auto* samples = context_->storage->mutable_cpu_profile_stack_sample_table();
+ samples->Insert({ts, *id, utid, 0});
+ return base::OkStatus();
+}
+
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.h b/src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.h
new file mode 100644
index 0000000..bdb2e78
--- /dev/null
+++ b/src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 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_IMPORTERS_COMMON_LEGACY_V8_CPU_PROFILE_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_LEGACY_V8_CPU_PROFILE_TRACKER_H_
+
+#include <cstdint>
+#include <optional>
+#include <utility>
+
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/flat_hash_map.h"
+#include "perfetto/ext/base/hash.h"
+#include "perfetto/ext/base/status_or.h"
+#include "perfetto/ext/base/string_view.h"
+#include "src/trace_processor/importers/common/virtual_memory_mapping.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto::trace_processor {
+
+// Stores interned callsites for given pid for legacy v8 samples.
+class LegacyV8CpuProfileTracker {
+ public:
+ explicit LegacyV8CpuProfileTracker(TraceProcessorContext*);
+
+ // Sets the start timestamp for the given pid.
+ void SetStartTsForSessionAndPid(uint64_t session_id,
+ uint32_t pid,
+ int64_t ts);
+
+ // Adds the callsite with for the given session and pid and given raw callsite
+ // id.
+ base::Status AddCallsite(uint64_t session_id,
+ uint32_t pid,
+ uint32_t raw_callsite_id,
+ std::optional<uint32_t> parent_raw_callsite_id,
+ base::StringView script_url,
+ base::StringView function_name);
+
+ // Increments the current timestamp for the given session and pid by
+ // |delta_ts| and returns the resulting full timestamp.
+ base::StatusOr<int64_t> AddDeltaAndGetTs(uint64_t session_id,
+ uint32_t pid,
+ int64_t delta_ts);
+
+ // Adds the sample with for the given session and pid/tid and given raw
+ // callsite id.
+ base::Status AddSample(int64_t ts,
+ uint64_t session_id,
+ uint32_t pid,
+ uint32_t tid,
+ uint32_t raw_callsite_id);
+
+ private:
+ struct State {
+ int64_t ts;
+ base::FlatHashMap<uint32_t, CallsiteId> callsites;
+ DummyMemoryMapping* mapping;
+ };
+ struct Hasher {
+ uint64_t operator()(const std::pair<uint64_t, uint32_t>& res) {
+ return base::Hasher::Combine(res.first, res.second);
+ }
+ };
+ base::FlatHashMap<std::pair<uint64_t, uint32_t>, State, Hasher>
+ state_by_session_and_pid_;
+
+ TraceProcessorContext* const context_;
+};
+
+} // namespace perfetto::trace_processor
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_LEGACY_V8_CPU_PROFILE_TRACKER_H_
diff --git a/src/trace_processor/importers/common/parser_types.h b/src/trace_processor/importers/common/parser_types.h
index 2a23b6c..bd32bde 100644
--- a/src/trace_processor/importers/common/parser_types.h
+++ b/src/trace_processor/importers/common/parser_types.h
@@ -37,6 +37,7 @@
int32_t next_prio;
StringPool::Id next_comm;
};
+static_assert(sizeof(InlineSchedSwitch) == 24);
// We enforce the exact size as it's critical for peak-memory use when sorting
// data in trace processor that this struct is as small as possible.
@@ -91,6 +92,14 @@
};
static_assert(sizeof(TracePacketData) % 8 == 0);
+struct alignas(8) LegacyV8CpuProfileEvent {
+ uint64_t session_id;
+ uint32_t pid;
+ uint32_t tid;
+ uint32_t callsite_id;
+};
+static_assert(sizeof(LegacyV8CpuProfileEvent) % 8 == 0);
+
} // namespace perfetto::trace_processor
#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_PARSER_TYPES_H_
diff --git a/src/trace_processor/importers/common/trace_parser.h b/src/trace_processor/importers/common/trace_parser.h
index 2bf3f3a..cf7c84a 100644
--- a/src/trace_processor/importers/common/trace_parser.h
+++ b/src/trace_processor/importers/common/trace_parser.h
@@ -37,6 +37,7 @@
struct InlineSchedWaking;
struct TracePacketData;
struct TrackEventData;
+struct LegacyV8CpuProfileEvent;
class ProtoTraceParser {
public:
@@ -47,6 +48,7 @@
virtual void ParseFtraceEvent(uint32_t, int64_t, TracePacketData) = 0;
virtual void ParseInlineSchedSwitch(uint32_t, int64_t, InlineSchedSwitch) = 0;
virtual void ParseInlineSchedWaking(uint32_t, int64_t, InlineSchedWaking) = 0;
+ virtual void ParseLegacyV8ProfileEvent(int64_t, LegacyV8CpuProfileEvent) = 0;
};
class JsonTraceParser {
diff --git a/src/trace_processor/importers/common/virtual_memory_mapping.cc b/src/trace_processor/importers/common/virtual_memory_mapping.cc
index 99aa23b..562049e 100644
--- a/src/trace_processor/importers/common/virtual_memory_mapping.cc
+++ b/src/trace_processor/importers/common/virtual_memory_mapping.cc
@@ -145,10 +145,11 @@
PERFETTO_CHECK(symbol_set_id == symbol_id.value);
- const FrameId frame_id = context()
- ->storage->mutable_stack_profile_frame_table()
- ->Insert({key.function_name_id, mapping_id(), 0})
- .id;
+ const FrameId frame_id =
+ context()
+ ->storage->mutable_stack_profile_frame_table()
+ ->Insert({key.function_name_id, mapping_id(), 0, symbol_set_id})
+ .id;
interned_dummy_frames_.Insert(key, frame_id);
return frame_id;
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_impl.cc b/src/trace_processor/importers/proto/proto_trace_parser_impl.cc
index 68a30bd..393bd79 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_impl.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_impl.cc
@@ -33,6 +33,7 @@
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/cpu_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
+#include "src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.h"
#include "src/trace_processor/importers/common/metadata_tracker.h"
#include "src/trace_processor/importers/common/parser_types.h"
#include "src/trace_processor/importers/common/process_tracker.h"
@@ -157,6 +158,18 @@
context_->args_tracker->Flush();
}
+void ProtoTraceParserImpl::ParseLegacyV8ProfileEvent(
+ int64_t ts,
+ LegacyV8CpuProfileEvent event) {
+ base::Status status = context_->legacy_v8_cpu_profile_tracker->AddSample(
+ ts, event.session_id, event.pid, event.tid, event.callsite_id);
+ if (!status.ok()) {
+ context_->storage->IncrementStats(
+ stats::legacy_v8_cpu_profile_invalid_sample);
+ }
+ context_->args_tracker->Flush();
+}
+
void ProtoTraceParserImpl::ParseChromeEvents(int64_t ts, ConstBytes blob) {
TraceStorage* storage = context_->storage.get();
protos::pbzero::ChromeEventBundle::Decoder bundle(blob.data, blob.size);
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_impl.h b/src/trace_processor/importers/proto/proto_trace_parser_impl.h
index 0c1db93..f6b2304 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_impl.h
+++ b/src/trace_processor/importers/proto/proto_trace_parser_impl.h
@@ -61,6 +61,8 @@
int64_t /*ts*/,
InlineSchedWaking data) override;
+ void ParseLegacyV8ProfileEvent(int64_t ts, LegacyV8CpuProfileEvent) override;
+
private:
StringId GetMetatraceInternedString(uint64_t iid);
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index 96c367c..360126c 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -39,6 +39,7 @@
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
#include "src/trace_processor/importers/common/global_args_tracker.h"
+#include "src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.h"
#include "src/trace_processor/importers/common/parser_types.h"
#include "src/trace_processor/importers/common/process_track_translation_table.h"
#include "src/trace_processor/importers/common/process_tracker.h"
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.cc b/src/trace_processor/importers/proto/track_event_tokenizer.cc
index be85689..268f45f 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.cc
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.cc
@@ -23,6 +23,7 @@
#include <string>
#include <utility>
+#include "perfetto/base/compiler.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/status.h"
#include "perfetto/ext/base/status_or.h"
@@ -34,6 +35,7 @@
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
+#include "src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.h"
#include "src/trace_processor/importers/common/metadata_tracker.h"
#include "src/trace_processor/importers/common/parser_types.h"
#include "src/trace_processor/importers/common/process_tracker.h"
@@ -288,6 +290,15 @@
return ModuleResult::Handled();
}
+ // Handle legacy sample events which might have timestamps embedded inside.
+ if (PERFETTO_UNLIKELY(event.has_legacy_event())) {
+ protos::pbzero::TrackEvent::LegacyEvent::Decoder leg(event.legacy_event());
+ if (PERFETTO_UNLIKELY(leg.phase() == 'P')) {
+ RETURN_IF_ERROR(TokenizeLegacySampleEvent(
+ event, leg, *data.trace_packet_data.sequence_state));
+ }
+ }
+
if (event.has_thread_time_delta_us()) {
// Delta timestamps require a valid ThreadDescriptor packet since the last
// packet loss.
@@ -437,4 +448,76 @@
return base::OkStatus();
}
+base::Status TrackEventTokenizer::TokenizeLegacySampleEvent(
+ const protos::pbzero::TrackEvent::Decoder& event,
+ const protos::pbzero::TrackEvent::LegacyEvent::Decoder& legacy,
+ PacketSequenceStateGeneration& state) {
+ // We are just trying to parse out the V8 profiling events into the cpu
+ // sampling tables: if we don't have JSON enabled, just don't do this.
+#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
+ for (auto it = event.debug_annotations(); it; ++it) {
+ protos::pbzero::DebugAnnotation::Decoder da(*it);
+ auto* interned_name = state.LookupInternedMessage<
+ protos::pbzero::InternedData::kDebugAnnotationNamesFieldNumber,
+ protos::pbzero::DebugAnnotationName>(da.name_iid());
+ base::StringView name(interned_name->name());
+ if (name != "data" || !da.has_legacy_json_value()) {
+ continue;
+ }
+ auto opt_val = json::ParseJsonString(da.legacy_json_value());
+ if (!opt_val) {
+ continue;
+ }
+ const auto& val = *opt_val;
+ if (val.isMember("startTime")) {
+ ASSIGN_OR_RETURN(int64_t ts, context_->clock_tracker->ToTraceTime(
+ protos::pbzero::BUILTIN_CLOCK_MONOTONIC,
+ val["startTime"].asInt64() * 1000));
+ context_->legacy_v8_cpu_profile_tracker->SetStartTsForSessionAndPid(
+ legacy.unscoped_id(), static_cast<uint32_t>(state.pid()), ts);
+ continue;
+ }
+ const auto& profile = val["cpuProfile"];
+ for (const auto& n : profile["nodes"]) {
+ uint32_t node_id = n["id"].asUInt();
+ std::optional<uint32_t> parent_node_id =
+ n.isMember("parent") ? std::make_optional(n["parent"].asUInt())
+ : std::nullopt;
+ const auto& frame = n["callFrame"];
+ base::StringView url =
+ frame.isMember("url") ? frame["url"].asCString() : base::StringView();
+ base::StringView function_name = frame["functionName"].asCString();
+ base::Status status =
+ context_->legacy_v8_cpu_profile_tracker->AddCallsite(
+ legacy.unscoped_id(), static_cast<uint32_t>(state.pid()), node_id,
+ parent_node_id, url, function_name);
+ if (!status.ok()) {
+ context_->storage->IncrementStats(
+ stats::legacy_v8_cpu_profile_invalid_callsite);
+ continue;
+ }
+ }
+ const auto& samples = profile["samples"];
+ const auto& deltas = val["timeDeltas"];
+ if (samples.size() != deltas.size()) {
+ return base::ErrStatus(
+ "v8 legacy profile: samples and timestamps do not have same size");
+ }
+ for (uint32_t i = 0; i < samples.size(); ++i) {
+ ASSIGN_OR_RETURN(
+ int64_t ts,
+ context_->legacy_v8_cpu_profile_tracker->AddDeltaAndGetTs(
+ legacy.unscoped_id(), static_cast<uint32_t>(state.pid()),
+ deltas[i].asInt64() * 1000));
+ context_->sorter->PushLegacyV8CpuProfileEvent(
+ ts, legacy.unscoped_id(), static_cast<uint32_t>(state.pid()),
+ static_cast<uint32_t>(state.tid()), samples[i].asUInt());
+ }
+ }
+#else
+ base::ignore_result(event, legacy, state);
+#endif
+ return base::OkStatus();
+}
+
} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.h b/src/trace_processor/importers/proto/track_event_tokenizer.h
index 743258c..0627562 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.h
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.h
@@ -78,6 +78,10 @@
protozero::RepeatedFieldIterator<T> value_it,
protozero::RepeatedFieldIterator<uint64_t> packet_track_uuid_it,
protozero::RepeatedFieldIterator<uint64_t> default_track_uuid_it);
+ base::Status TokenizeLegacySampleEvent(
+ const protos::pbzero::TrackEvent_Decoder&,
+ const protos::pbzero::TrackEvent_LegacyEvent_Decoder&,
+ PacketSequenceStateGeneration& state);
TraceProcessorContext* context_;
TrackEventTracker* track_event_tracker_;
diff --git a/src/trace_processor/sorter/trace_sorter.cc b/src/trace_processor/sorter/trace_sorter.cc
index 2316dae..924660a 100644
--- a/src/trace_processor/sorter/trace_sorter.cc
+++ b/src/trace_processor/sorter/trace_sorter.cc
@@ -230,6 +230,10 @@
context.android_log_event_parser->ParseAndroidLogEvent(
event.ts, token_buffer_.Extract<AndroidLogEvent>(id));
return;
+ case TimestampedEvent::Type::kLegacyV8CpuProfileEvent:
+ context.proto_trace_parser->ParseLegacyV8ProfileEvent(
+ event.ts, token_buffer_.Extract<LegacyV8CpuProfileEvent>(id));
+ return;
case TimestampedEvent::Type::kInlineSchedSwitch:
case TimestampedEvent::Type::kInlineSchedWaking:
case TimestampedEvent::Type::kEtwEvent:
@@ -259,6 +263,7 @@
case TimestampedEvent::Type::kJsonValue:
case TimestampedEvent::Type::kFuchsiaRecord:
case TimestampedEvent::Type::kAndroidLogEvent:
+ case TimestampedEvent::Type::kLegacyV8CpuProfileEvent:
PERFETTO_FATAL("Invalid event type");
}
PERFETTO_FATAL("For GCC");
@@ -290,6 +295,7 @@
case TimestampedEvent::Type::kJsonValue:
case TimestampedEvent::Type::kFuchsiaRecord:
case TimestampedEvent::Type::kAndroidLogEvent:
+ case TimestampedEvent::Type::kLegacyV8CpuProfileEvent:
PERFETTO_FATAL("Invalid event type");
}
PERFETTO_FATAL("For GCC");
@@ -331,6 +337,9 @@
case TimestampedEvent::Type::kAndroidLogEvent:
base::ignore_result(token_buffer_.Extract<AndroidLogEvent>(id));
return;
+ case TimestampedEvent::Type::kLegacyV8CpuProfileEvent:
+ base::ignore_result(token_buffer_.Extract<LegacyV8CpuProfileEvent>(id));
+ return;
}
PERFETTO_FATAL("For GCC");
}
diff --git a/src/trace_processor/sorter/trace_sorter.h b/src/trace_processor/sorter/trace_sorter.h
index b89a25a..183f376 100644
--- a/src/trace_processor/sorter/trace_sorter.h
+++ b/src/trace_processor/sorter/trace_sorter.h
@@ -209,6 +209,21 @@
UpdateAppendMaxTs(queue);
}
+ inline void PushLegacyV8CpuProfileEvent(
+ int64_t timestamp,
+ uint64_t session_id,
+ uint32_t pid,
+ uint32_t tid,
+ uint32_t callsite_id,
+ std::optional<MachineId> machine_id = std::nullopt) {
+ TraceTokenBuffer::Id id = token_buffer_.Append(
+ LegacyV8CpuProfileEvent{session_id, pid, tid, callsite_id});
+ auto* queue = GetQueue(0, machine_id);
+ queue->Append(timestamp, TimestampedEvent::Type::kLegacyV8CpuProfileEvent,
+ id);
+ UpdateAppendMaxTs(queue);
+ }
+
inline void PushInlineFtraceEvent(
uint32_t cpu,
int64_t timestamp,
@@ -284,7 +299,8 @@
kSystraceLine,
kEtwEvent,
kAndroidLogEvent,
- kMax = kAndroidLogEvent,
+ kLegacyV8CpuProfileEvent,
+ kMax = kLegacyV8CpuProfileEvent,
};
// Number of bits required to store the max element in |Type|.
diff --git a/src/trace_processor/storage/stats.h b/src/trace_processor/storage/stats.h
index 5d340bb..8838b4f 100644
--- a/src/trace_processor/storage/stats.h
+++ b/src/trace_processor/storage/stats.h
@@ -379,7 +379,12 @@
F(mali_unknown_mcu_state_id, kSingle, kError, kAnalysis, \
"An invalid Mali GPU MCU state ID was detected."), \
F(pixel_modem_negative_timestamp, kSingle, kError, kAnalysis, \
- "A negative timestamp was received from a Pixel modem event.")
+ "A negative timestamp was received from a Pixel modem event."), \
+ F(legacy_v8_cpu_profile_invalid_callsite, kSingle, kInfo, kAnalysis, \
+ "Indicates a callsite in legacy v8 CPU profiling is invalid."), \
+ F(legacy_v8_cpu_profile_invalid_sample, kSingle, kError, kAnalysis, \
+ "Indicates a sample in legacy v8 CPU profile is invalid. This will " \
+ "cause CPU samples to be missing in the UI.")
// clang-format on
enum Type {
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index d6493a9..53876b0 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -30,6 +30,7 @@
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
#include "src/trace_processor/importers/common/global_args_tracker.h"
+#include "src/trace_processor/importers/common/legacy_v8_cpu_profile_tracker.h"
#include "src/trace_processor/importers/common/machine_tracker.h"
#include "src/trace_processor/importers/common/mapping_tracker.h"
#include "src/trace_processor/importers/common/metadata_tracker.h"
@@ -105,6 +106,8 @@
});
trace_file_tracker = std::make_unique<TraceFileTracker>(this);
+ legacy_v8_cpu_profile_tracker =
+ std::make_unique<LegacyV8CpuProfileTracker>(this);
}
TraceProcessorContext::TraceProcessorContext() = default;
diff --git a/src/trace_processor/types/trace_processor_context.h b/src/trace_processor/types/trace_processor_context.h
index b9f4ae6..3e7ba55 100644
--- a/src/trace_processor/types/trace_processor_context.h
+++ b/src/trace_processor/types/trace_processor_context.h
@@ -48,6 +48,7 @@
class HeapGraphTracker;
class InstrumentsRowParser;
class JsonTraceParser;
+class LegacyV8CpuProfileTracker;
class MachineTracker;
class MappingTracker;
class MetadataTracker;
@@ -130,6 +131,7 @@
std::unique_ptr<MetadataTracker> metadata_tracker;
std::unique_ptr<CpuTracker> cpu_tracker;
std::unique_ptr<TraceFileTracker> trace_file_tracker;
+ std::unique_ptr<LegacyV8CpuProfileTracker> legacy_v8_cpu_profile_tracker;
// These fields are stored as pointers to Destructible objects rather than
// their actual type (a subclass of Destructible), as the concrete subclass
diff --git a/test/data/v8-samples.pftrace.sha256 b/test/data/v8-samples.pftrace.sha256
new file mode 100644
index 0000000..c9a7d2f
--- /dev/null
+++ b/test/data/v8-samples.pftrace.sha256
@@ -0,0 +1 @@
+564159912db8d8252562f143e6206ae9964759e16193ebd3addd04823d02a6ae
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/parser/chrome/tests_v8.py b/test/trace_processor/diff_tests/parser/chrome/tests_v8.py
index d4a0dc4..f77a47a 100644
--- a/test/trace_processor/diff_tests/parser/chrome/tests_v8.py
+++ b/test/trace_processor/diff_tests/parser/chrome/tests_v8.py
@@ -100,3 +100,41 @@
0
"""),
)
+
+ def test_v8_cpu_samples(self):
+ return DiffTestBlueprint(
+ trace=DataPath('v8-samples.pftrace'),
+ query='''
+ include perfetto module callstacks.stack_profile;
+
+ select name, source_file, self_count
+ from _callstacks_for_cpu_profile_stack_samples!(
+ cpu_profile_stack_sample
+ )
+ where self_count > 0
+ order by self_count desc
+ limit 20
+ ''',
+ out=Csv('''
+ "name","source_file","self_count"
+ "(program)","[NULL]",17083
+ "(program)","[NULL]",15399
+ "(program)","[NULL]",9853
+ "(program)","[NULL]",9391
+ "(program)","[NULL]",7299
+ "(program)","[NULL]",5245
+ "(program)","[NULL]",2443
+ "(garbage collector)","[NULL]",107
+ "_.mg","chrome-untrusted://new-tab-page/one-google-bar?paramsencoded=",38
+ "(garbage collector)","[NULL]",34
+ "","https://www.google.com/xjs/_/js/k=xjs.hd.en.nSJdbfIGUiE.O/am=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAACAEKAAAABR4AAAAgAAAAAAAAAAQIAQDEAQAAAgA4AAAEAQAEABQQAAAKEATgUTYAgAAwAQAIAAAQAAACQAAACAAAAAMAACAIAAAAAKAAAAAAAAAAAAAAAAAAYAABBAAAAAAAAAAAAIACAAAAoAMAAAAAgAAAgIAAANghAwgAAAQAAACgDwCCB8AghQcAAAAAAAAAAAAAAAKQIJgLCSgIQAAAAAAAAAAAAAAAAACkpIkLCw/d=1/ed=1/dg=3/br=1/rs=ACT90oH8sSQRHJq5R0DO9ABVW-vZJa5Baw/ee=ALeJib:B8gLwd;AfeaP:TkrAjf;BMxAGc:E5bFse;BgS6mb:fidj5d;BjwMce:cXX2Wb;CxXAWb:YyRLvc;DULqB:RKfG5c;Dkk6ge:wJqrrd;DpcR3d:zL72xf;EABSZ:MXZt9d;ESrPQc:mNTJvc;EVNhjf:pw70Gc;EmZ2Bf:zr1jrb;EnlcNd:WeHg4;Erl4fe:FloWmf,FloWmf;F9mqte:UoRcbe;Fmv9Nc:O1Tzwc;G0KhTb:LIaoZ;G6wU6e:hezEbd;GleZL:J1A7Od;HMDDWe:G8QUdb;HoYVKb:PkDN7e;HqeXPd:cmbnH;IBADCc:RYquRb;IZrNqe:P8ha2c;IoGlCf:b5lhvb;IsdWVc:qzxzOb;JXS8fb:Qj0suc;JbMT3:M25sS;JsbNhc:Xd8iUd;KOxcK:OZqGte;KQzWid:ZMKkN;KcokUb:KiuZBf;KpRAue:Tia57b;LBgRLc:SdcwHb,XVMNvd;LEikZe:byfTOb,lsjVmc;LXA8b:q7OdKd;LsNahb:ucGLNb;Me32dd:MEeYgc;NPKaK:SdcwHb;NSEoX:lazG7b;Np8Qkd:Dpx6qc;Nyt6ic:jn2sGd;OgagBe:",33
+ "_.m.Ddb","https://www.google.com/xjs/_/js/k=xjs.hd.en.nSJdbfIGUiE.O/am=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAACAEKAAAABR4AAAAgAAAAAAAAAAQIAQDEAQAAAgA4AAAEAQAEABQQAAAKEATgUTYAgAAwAQAIAAAQAAACQAAACAAAAAMAACAIAAAAAKAAAAAAAAAAAAAAAAAAYAABBAAAAAAAAAAAAIACAAAAoAMAAAAAgAAAgIAAANghAwgAAAQAAACgDwCCB8AghQcAAAAAAAAAAAAAAAKQIJgLCSgIQAAAAAAAAAAAAAAAAACkpIkLCw/d=1/ed=1/dg=3/br=1/rs=ACT90oH8sSQRHJq5R0DO9ABVW-vZJa5Baw/ee=ALeJib:B8gLwd;AfeaP:TkrAjf;BMxAGc:E5bFse;BgS6mb:fidj5d;BjwMce:cXX2Wb;CxXAWb:YyRLvc;DULqB:RKfG5c;Dkk6ge:wJqrrd;DpcR3d:zL72xf;EABSZ:MXZt9d;ESrPQc:mNTJvc;EVNhjf:pw70Gc;EmZ2Bf:zr1jrb;EnlcNd:WeHg4;Erl4fe:FloWmf,FloWmf;F9mqte:UoRcbe;Fmv9Nc:O1Tzwc;G0KhTb:LIaoZ;G6wU6e:hezEbd;GleZL:J1A7Od;HMDDWe:G8QUdb;HoYVKb:PkDN7e;HqeXPd:cmbnH;IBADCc:RYquRb;IZrNqe:P8ha2c;IoGlCf:b5lhvb;IsdWVc:qzxzOb;JXS8fb:Qj0suc;JbMT3:M25sS;JsbNhc:Xd8iUd;KOxcK:OZqGte;KQzWid:ZMKkN;KcokUb:KiuZBf;KpRAue:Tia57b;LBgRLc:SdcwHb,XVMNvd;LEikZe:byfTOb,lsjVmc;LXA8b:q7OdKd;LsNahb:ucGLNb;Me32dd:MEeYgc;NPKaK:SdcwHb;NSEoX:lazG7b;Np8Qkd:Dpx6qc;Nyt6ic:jn2sGd;OgagBe:",18
+ "da","https://www.google.com/",15
+ "","https://www.gstatic.com/_/mss/boq-one-google/_/js/k=boq-one-google.OneGoogleWidgetUi.en.Dv_TT86KXl4.es5.O/ck=boq-one-google.OneGoogleWidgetUi.xexmpZqkioA.L.B1.O/am=QKBgwGw/d=1/exm=_b,_tp/excm=_b,_tp,calloutview/ed=1/wt=2/ujg=1/rs=AM-SdHu61g-i-YBZiLcGm3tURf4VJO5hyA/ee=EVNhjf:pw70Gc;EmZ2Bf:zr1jrb;Erl4fe:FloWmf;JsbNhc:Xd8iUd;LBgRLc:SdcwHb;Me32dd:MEeYgc;NPKaK:SdcwHb;NSEoX:lazG7b;Oj465e:KG2eXe;Pjplud:EEDORb;QGR0gd:Mlhmy;SNUn3:ZwDk9d;a56pNe:JEfCwb;cEt90b:ws9Tlc;dIoSBb:SpsfSb;eBAeSb:zbML3c;iFQyKf:QIhFr;io8t5d:yDVVkb;kMFpHd:OTA3Ae;nAFL3:s39S4;oGtAuc:sOXFj;pXdRYb:MdUzUe;qddgKe:xQtZb;sP4Vbe:VwDzFe;uY49fb:COQbmf;ul9GGd:VDovNc;wR5FRb:O1Gjze;xqZiqf:wmnU7d;yxTchf:KUM7Z;zxnPse:GkRiKb/m=ws9Tlc,n73qwf,GkRiKb,e5qFLc,IZT63,UUJqVe,O1Gjze,byfTOb,lsjVmc,xUdipf,OTA3Ae,COQbmf,fKUV3e,aurFic,U0aPgd,ZwDk9d,V3dDOb,mI3LFb,yYB61,O6y8ed,PrPYRd,MpJwZc,LEikZe,NwH0H,OmgaI,lazG7b,XVMNvd,L1AAkb,KUM7Z,Mlhmy,s39S4,lwddkf,gychg,w9hDv,EEDORb,RMhBfe,SdcwHb,aW3pY,pw70Gc,EFQ78c,Ulmmrd,ZfAoz,mdR7q,wmnU7d,xQtZb,JNoxi,kWgXee,MI6k7c,kjKdXe,BVgquf,QIhFr,ov",13
+ "updateAttrs","https://ui.perfetto.dev/v46.0-0a53e685b/frontend_bundle.js",12
+ "","https://www.gstatic.com/_/mss/boq-one-google/_/js/k=boq-one-google.OneGoogleWidgetUi.en.Dv_TT86KXl4.es5.O/am=QKBgwGw/d=1/excm=_b,_tp,calloutview/ed=1/dg=0/wt=2/ujg=1/rs=AM-SdHsuxqEW2z6uUf-9MJvUVpOyFk0ecQ/m=_b,_tp",11
+ "a._isVisible","https://ogs.google.com/widget/callout?prid=19037050&pgid=19037049&puid=6a851fbb7ce797ac&eom=1&cce=1&dc=1&origin=https%3A%2F%2Fwww.google.com&cn=callout&pid=1&spid=538&hl=en&dm=",11
+ "","chrome-untrusted://read-anything-side-panel.top-chrome/read_anything.js",11
+ "","https://www.google.com/xjs/_/js/k=xjs.hd.en.nSJdbfIGUiE.O/ck=xjs.hd.F00K1IyvS9A.L.B1.O/am=IFEAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAIAAAEAAAAAAAASAEakAAABZ5sAMBiAAAABAAIAAQIAQDEAQAAAwQ4AAAEAQAUABQREAEKEgTgUTYAhIAwAQQoQAgUQAICQBCFCAAAAAMAACEIDDAMQKgAYBQgAAAAAEBABAAAYAA3BhAgAMAPAAAYAKICAAAhoAMQAAABgAJAgIACAtghAwgAAAQAAACgDwCCB8AghQcAAAAAAAAAAAAAAAKQIJgLCSgIQAAAAAAAAAAAAAAAAACkpIkLCw/d=0/dg=0/br=1/ujg=1/rs=ACT90oFYV6TnvY5P3NcVPbMRvVPRlxmm8A/m=sb_wiz,aa,abd,sytt,syts,sytn,syfx,sytr,sytd,sy101,syz7,syti,syz6,syto,sytq,sytm,syu7,sytb,syu8,syu9,syu0,syu4,sytj,syty,syu1,syu2,sytv,sytw,syte,sytf,sys4,syru,syrs,syrr,syth,syz5,syug,syuh,syuf,async,syvk,ifl,pHXghd,sf,sy1c2,sy1c5,sy4e0,sonic,TxCJfd,sy4e4,qzxzOb,IsdWVc,sy4e6,sy1gs,sy1d4,sy1d0,syrq,syro,syrp,syrn,syrm,sy4cl,sy4co,sy2ib,sy18p,sy18r,sy13l,sy13m,syrj,syrh,syfb,sybv,syby,sybt,sybx,sybw,sycp,spch,sys7,sys6,rtH1bd,sy1ea,sy19r,sy18g,syg9,sy1e9,sy13t,sy1e8,sy18h,sygb,sy1eb,SMquOb,sy8f,sygh,sygf,sygg,sygi,syge,sygp,sygn,sygl,sygd,sycm,sych,syck,syak,syac,syb6,syaj,syai,sya",10
+ "maybeUpdateMoreOptions","chrome-untrusted://read-anything-side-panel.top-chrome/read_anything.js",10
+ '''))