processor: Extract generations of incremental state into helper class
Adds a PacketSequenceStateGeneration class, which effectively
encapsulates the state pointer and generation data into a single object.
This way, it's possible to store a single pointer in
TimestampedTracePiece, rather than a pointer and index.
Bug: 123864183, 142557489
Change-Id: I14fd3d97ca67fb2ddaa33b23d4f28c4563affa41
diff --git a/Android.bp b/Android.bp
index 9a0c021..40693fa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -5812,6 +5812,7 @@
"src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc",
"src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc",
"src/trace_processor/importers/proto/args_table_utils.cc",
+ "src/trace_processor/importers/proto/packet_sequence_state.cc",
"src/trace_processor/importers/proto/proto_importer_module.cc",
"src/trace_processor/importers/proto/proto_trace_parser.cc",
"src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
diff --git a/BUILD b/BUILD
index b9f8000..f94416d 100644
--- a/BUILD
+++ b/BUILD
@@ -914,6 +914,7 @@
"src/trace_processor/importers/proto/args_table_utils.cc",
"src/trace_processor/importers/proto/args_table_utils.h",
"src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h",
+ "src/trace_processor/importers/proto/packet_sequence_state.cc",
"src/trace_processor/importers/proto/packet_sequence_state.h",
"src/trace_processor/importers/proto/proto_importer_module.cc",
"src/trace_processor/importers/proto/proto_importer_module.h",
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 097fd06..76835be 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -96,6 +96,7 @@
"importers/proto/args_table_utils.cc",
"importers/proto/args_table_utils.h",
"importers/proto/chrome_compositor_scheduler_state.descriptor.h",
+ "importers/proto/packet_sequence_state.cc",
"importers/proto/packet_sequence_state.h",
"importers/proto/proto_importer_module.cc",
"importers/proto/proto_importer_module.h",
diff --git a/src/trace_processor/importers/proto/args_table_utils.cc b/src/trace_processor/importers/proto/args_table_utils.cc
index aec9800..0727718 100644
--- a/src/trace_processor/importers/proto/args_table_utils.cc
+++ b/src/trace_processor/importers/proto/args_table_utils.cc
@@ -24,13 +24,12 @@
namespace perfetto {
namespace trace_processor {
-ProtoToArgsTable::ProtoToArgsTable(PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
- TraceProcessorContext* context,
- std::string starting_prefix,
- size_t prefix_size_hint)
- : state_{context, sequence_state, sequence_state_generation},
- prefix_(std::move(starting_prefix)) {
+ProtoToArgsTable::ProtoToArgsTable(
+ PacketSequenceStateGeneration* sequence_state,
+ TraceProcessorContext* context,
+ std::string starting_prefix,
+ size_t prefix_size_hint)
+ : state_{context, sequence_state}, prefix_(std::move(starting_prefix)) {
prefix_.reserve(prefix_size_hint);
}
diff --git a/src/trace_processor/importers/proto/args_table_utils.h b/src/trace_processor/importers/proto/args_table_utils.h
index 1ba6e9a..9eb95b2 100644
--- a/src/trace_processor/importers/proto/args_table_utils.h
+++ b/src/trace_processor/importers/proto/args_table_utils.h
@@ -71,8 +71,7 @@
public:
struct ParsingOverrideState {
TraceProcessorContext* context;
- PacketSequenceState* sequence_state;
- size_t sequence_generation;
+ PacketSequenceStateGeneration* sequence_state;
};
using ParsingOverride = bool (*)(const ParsingOverrideState& state,
const protozero::Field&,
@@ -99,14 +98,13 @@
std::string* str_;
};
- // |sequence_state| and |sequence_state_generation| provide access to
- // interning data. |context| provides access to storage.
+ // |sequence_state| provides access to interning data.
+ // |context| provides access to storage.
//
// |starting_prefix| will be prepended to all columns.
// |prefix_size_hint| allows the class to upfront reserve the expected string
// size needed.
- ProtoToArgsTable(PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
+ ProtoToArgsTable(PacketSequenceStateGeneration* sequence_state,
TraceProcessorContext* context,
std::string starting_prefix = "",
size_t prefix_size_hint = 64);
diff --git a/src/trace_processor/importers/proto/args_table_utils_unittest.cc b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
index d5d3a3b..4cc03e9 100644
--- a/src/trace_processor/importers/proto/args_table_utils_unittest.cc
+++ b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
@@ -77,8 +77,7 @@
};
TEST_F(ArgsTableUtilsTest, EnsureChromeCompositorStateDescriptorParses) {
- ProtoToArgsTable helper(sequence_state_.get(),
- sequence_state_->current_generation(), &context_, "",
+ ProtoToArgsTable helper(sequence_state_->current_generation(), &context_, "",
0);
auto status = helper.AddProtoFileDescriptor(
kChromeCompositorSchedulerStateDescriptor.data(),
@@ -89,8 +88,7 @@
}
TEST_F(ArgsTableUtilsTest, EnsureTestMessageProtoParses) {
- ProtoToArgsTable helper(sequence_state_.get(),
- sequence_state_->current_generation(), &context_, "",
+ ProtoToArgsTable helper(sequence_state_->current_generation(), &context_, "",
0);
auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
kTestMessagesDescriptor.size());
@@ -127,8 +125,7 @@
auto binary_proto = msg.SerializeAsArray();
storage_->mutable_track_table()->Insert({});
- ProtoToArgsTable helper(sequence_state_.get(),
- sequence_state_->current_generation(), &context_, "",
+ ProtoToArgsTable helper(sequence_state_->current_generation(), &context_, "",
0);
auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
kTestMessagesDescriptor.size());
@@ -201,8 +198,7 @@
auto binary_proto = msg.SerializeAsArray();
storage_->mutable_track_table()->Insert({});
- ProtoToArgsTable helper(sequence_state_.get(),
- sequence_state_->current_generation(), &context_, "",
+ ProtoToArgsTable helper(sequence_state_->current_generation(), &context_, "",
0);
auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
kTestMessagesDescriptor.size());
@@ -231,8 +227,7 @@
auto binary_proto = msg.SerializeAsArray();
storage_->mutable_track_table()->Insert({});
- ProtoToArgsTable helper(sequence_state_.get(),
- sequence_state_->current_generation(), &context_, "",
+ ProtoToArgsTable helper(sequence_state_->current_generation(), &context_, "",
0);
auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
kTestMessagesDescriptor.size());
@@ -261,8 +256,7 @@
auto binary_proto = msg.SerializeAsArray();
storage_->mutable_track_table()->Insert({});
- ProtoToArgsTable helper(sequence_state_.get(),
- sequence_state_->current_generation(), &context_, "",
+ ProtoToArgsTable helper(sequence_state_->current_generation(), &context_, "",
0);
auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
kTestMessagesDescriptor.size());
@@ -304,8 +298,7 @@
auto binary_proto = msg.SerializeAsArray();
storage_->mutable_track_table()->Insert({});
- ProtoToArgsTable helper(sequence_state_.get(),
- sequence_state_->current_generation(), &context_, "",
+ ProtoToArgsTable helper(sequence_state_->current_generation(), &context_, "",
0);
auto status = helper.AddProtoFileDescriptor(kTestMessagesDescriptor.data(),
kTestMessagesDescriptor.size());
@@ -361,8 +354,7 @@
protos::pbzero::InternedData::kSourceLocationsFieldNumber,
std::move(blob));
- ProtoToArgsTable helper(sequence_state_.get(),
- sequence_state_->current_generation(), &context_, "",
+ ProtoToArgsTable helper(sequence_state_->current_generation(), &context_, "",
0);
// Now we override the behaviour of |value_c| so we can expand the iid into
// multiple args rows.
@@ -373,8 +365,7 @@
EXPECT_EQ(field.type(), protozero::proto_utils::ProtoWireType::kVarInt);
auto* decoder = state.sequence_state->LookupInternedMessage<
protos::pbzero::InternedData::kSourceLocationsFieldNumber,
- protos::pbzero::SourceLocation>(state.sequence_generation,
- field.as_uint64());
+ protos::pbzero::SourceLocation>(field.as_uint64());
if (!decoder) {
// Lookup failed fall back on default behaviour.
return false;
diff --git a/src/trace_processor/importers/proto/graphics_event_module.cc b/src/trace_processor/importers/proto/graphics_event_module.cc
index e9fda0a..38979f2 100644
--- a/src/trace_processor/importers/proto/graphics_event_module.cc
+++ b/src/trace_processor/importers/proto/graphics_event_module.cc
@@ -53,10 +53,8 @@
return;
case TracePacket::kVulkanMemoryEventFieldNumber:
PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
- parser_.ParseVulkanMemoryEvent(
- ttp.packet_data.packet_sequence_state,
- ttp.packet_data.packet_sequence_state_generation,
- decoder.vulkan_memory_event());
+ parser_.ParseVulkanMemoryEvent(ttp.packet_data.sequence_state,
+ decoder.vulkan_memory_event());
return;
case TracePacket::kVulkanApiEventFieldNumber:
parser_.ParseVulkanApiEvent(decoder.vulkan_api_event());
diff --git a/src/trace_processor/importers/proto/graphics_event_parser.cc b/src/trace_processor/importers/proto/graphics_event_parser.cc
index 240c4d9..9f0f163 100644
--- a/src/trace_processor/importers/proto/graphics_event_parser.cc
+++ b/src/trace_processor/importers/proto/graphics_event_parser.cc
@@ -570,8 +570,7 @@
}
void GraphicsEventParser::ParseVulkanMemoryEvent(
- PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration* sequence_state,
ConstBytes blob) {
using protos::pbzero::InternedData;
VulkanMemoryEvent::Decoder vulkan_memory_event(blob.data, blob.size);
@@ -599,7 +598,7 @@
vulkan_memory_event_row.function_name =
vulkan_memory_tracker_
.GetInternedString<InternedData::kFunctionNamesFieldNumber>(
- sequence_state, sequence_state_generation,
+ sequence_state,
static_cast<uint64_t>(vulkan_memory_event.caller_iid()));
}
if (vulkan_memory_event.has_object_handle())
@@ -634,8 +633,7 @@
auto key_id =
vulkan_memory_tracker_
.GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
- sequence_state, sequence_state_generation,
- static_cast<uint64_t>(annotation.key_iid()));
+ sequence_state, static_cast<uint64_t>(annotation.key_iid()));
if (annotation.has_int_value()) {
inserter.AddArg(key_id, Variadic::Integer(annotation.int_value()));
@@ -645,7 +643,7 @@
auto string_id =
vulkan_memory_tracker_
.GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
- sequence_state, sequence_state_generation,
+ sequence_state,
static_cast<uint64_t>(annotation.string_iid()));
inserter.AddArg(key_id, Variadic::String(string_id.id));
diff --git a/src/trace_processor/importers/proto/graphics_event_parser.h b/src/trace_processor/importers/proto/graphics_event_parser.h
index 7d31175..d9e71c3 100644
--- a/src/trace_processor/importers/proto/graphics_event_parser.h
+++ b/src/trace_processor/importers/proto/graphics_event_parser.h
@@ -60,9 +60,7 @@
void ParseGraphicsFrameEvent(int64_t timestamp, ConstBytes);
void ParseGpuLog(int64_t ts, ConstBytes);
- void ParseVulkanMemoryEvent(PacketSequenceState*,
- size_t sequence_state_generation,
- ConstBytes);
+ void ParseVulkanMemoryEvent(PacketSequenceStateGeneration*, ConstBytes);
void UpdateVulkanMemoryAllocationCounters(UniquePid,
const VulkanMemoryEvent::Decoder&);
diff --git a/src/trace_processor/importers/proto/packet_sequence_state.cc b/src/trace_processor/importers/proto/packet_sequence_state.cc
new file mode 100644
index 0000000..c63c2d7
--- /dev/null
+++ b/src/trace_processor/importers/proto/packet_sequence_state.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 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/proto/packet_sequence_state.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+void PacketSequenceStateGeneration::InternMessage(uint32_t field_id,
+ TraceBlobView message) {
+ constexpr auto kIidFieldNumber = 1;
+
+ uint64_t iid = 0;
+ auto message_start = message.data();
+ auto message_size = message.length();
+ protozero::ProtoDecoder decoder(message_start, message_size);
+
+ auto field = decoder.FindField(kIidFieldNumber);
+ if (PERFETTO_UNLIKELY(!field)) {
+ PERFETTO_DLOG("Interned message without interning_id");
+ state_->context()->storage->IncrementStats(
+ stats::interned_data_tokenizer_errors);
+ return;
+ }
+ iid = field.as_uint64();
+
+ auto res = interned_data_[field_id].emplace(
+ iid, InternedMessageView(std::move(message)));
+
+ // If a message with this ID is already interned in the same generation,
+ // its data should not have changed (this is forbidden by the InternedData
+ // proto).
+ // TODO(eseckler): This DCHECK assumes that the message is encoded the
+ // same way if it is re-emitted.
+ PERFETTO_DCHECK(res.second ||
+ (res.first->second.message().length() == message_size &&
+ memcmp(res.first->second.message().data(), message_start,
+ message_size) == 0));
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/packet_sequence_state.h b/src/trace_processor/importers/proto/packet_sequence_state.h
index c020758..903f99d 100644
--- a/src/trace_processor/importers/proto/packet_sequence_state.h
+++ b/src/trace_processor/importers/proto/packet_sequence_state.h
@@ -42,127 +42,174 @@
#define PERFETTO_TYPE_IDENTIFIER nullptr
#endif // PERFETTO_DCHECK_IS_ON()
+// Entry in an interning index, refers to the interned message.
+class InternedMessageView {
+ public:
+ InternedMessageView(TraceBlobView msg) : message_(std::move(msg)) {}
+
+ InternedMessageView(InternedMessageView&&) noexcept = default;
+ InternedMessageView& operator=(InternedMessageView&&) = default;
+
+ // Allow copy by cloning the TraceBlobView. This is required for
+ // UpdateTracePacketDefaults().
+ InternedMessageView(const InternedMessageView& view)
+ : message_(view.message_.slice(0, view.message_.length())) {}
+ InternedMessageView& operator=(const InternedMessageView& view) {
+ this->message_ = view.message_.slice(0, view.message_.length());
+ this->decoder_ = nullptr;
+ this->decoder_type_ = nullptr;
+ this->submessages_.clear();
+ return *this;
+ }
+
+ // Lazily initializes and returns the decoder object for the message. The
+ // decoder is stored in the InternedMessageView to avoid having to parse the
+ // message multiple times.
+ template <typename MessageType>
+ typename MessageType::Decoder* GetOrCreateDecoder() {
+ if (!decoder_) {
+ // Lazy init the decoder and save it away, so that we don't have to
+ // reparse the message every time we access the interning entry.
+ decoder_ = std::unique_ptr<void, std::function<void(void*)>>(
+ new typename MessageType::Decoder(message_.data(), message_.length()),
+ [](void* obj) {
+ delete reinterpret_cast<typename MessageType::Decoder*>(obj);
+ });
+ decoder_type_ = PERFETTO_TYPE_IDENTIFIER;
+ }
+ // Verify that the type of the decoder didn't change.
+ if (PERFETTO_TYPE_IDENTIFIER &&
+ strcmp(decoder_type_,
+ // GCC complains if this arg can be null.
+ PERFETTO_TYPE_IDENTIFIER ? PERFETTO_TYPE_IDENTIFIER : "") != 0) {
+ PERFETTO_FATAL(
+ "Interning entry accessed under different types! previous type: "
+ "%s. new type: %s.",
+ decoder_type_, __PRETTY_FUNCTION__);
+ }
+ return reinterpret_cast<typename MessageType::Decoder*>(decoder_.get());
+ }
+
+ // Lookup a submessage of the interned message, which is then itself stored
+ // as InternedMessageView, so that we only need to parse it once. Returns
+ // nullptr if the field isn't set.
+ // TODO(eseckler): Support repeated fields.
+ template <typename MessageType, uint32_t FieldId>
+ InternedMessageView* GetOrCreateSubmessageView() {
+ auto it = submessages_.find(FieldId);
+ if (it != submessages_.end())
+ return it->second.get();
+ auto* decoder = GetOrCreateDecoder<MessageType>();
+ // Calls the at() template method on the decoder.
+ auto field = decoder->template at<FieldId>().as_bytes();
+ if (!field.data)
+ return nullptr;
+ const size_t offset = message_.offset_of(field.data);
+ TraceBlobView submessage = message_.slice(offset, field.size);
+ InternedMessageView* submessage_view =
+ new InternedMessageView(std::move(submessage));
+ submessages_.emplace_hint(
+ it, FieldId, std::unique_ptr<InternedMessageView>(submessage_view));
+ return submessage_view;
+ }
+
+ const TraceBlobView& message() { return message_; }
+
+ private:
+ using SubMessageViewMap =
+ std::unordered_map<uint32_t /*field_id*/,
+ std::unique_ptr<InternedMessageView>>;
+
+ TraceBlobView message_;
+
+ // Stores the decoder for the message_, so that the message does not have to
+ // be re-decoded every time the interned message is looked up. Lazily
+ // initialized in GetOrCreateDecoder(). Since we don't know the type of the
+ // decoder until GetOrCreateDecoder() is called, we store the decoder as a
+ // void* unique_pointer with a destructor function that's supplied in
+ // GetOrCreateDecoder() when the decoder is created.
+ std::unique_ptr<void, std::function<void(void*)>> decoder_;
+
+ // Type identifier for the decoder. Only valid in debug builds and on
+ // supported platforms. Used to verify that GetOrCreateDecoder() is always
+ // called with the same template argument.
+ const char* decoder_type_ = nullptr;
+
+ // Views of submessages of the interned message. Submessages are lazily
+ // added by GetOrCreateSubmessageView(). By storing submessages and their
+ // decoders, we avoid having to decode submessages multiple times if they
+ // looked up often.
+ SubMessageViewMap submessages_;
+};
+
+using InternedMessageMap =
+ std::unordered_map<uint64_t /*iid*/, InternedMessageView>;
+using InternedFieldMap =
+ std::unordered_map<uint32_t /*field_id*/, InternedMessageMap>;
+
+class PacketSequenceState;
+
+class PacketSequenceStateGeneration {
+ public:
+ // Returns |nullptr| if the message with the given |iid| was not found (also
+ // records a stat in this case).
+ template <uint32_t FieldId, typename MessageType>
+ typename MessageType::Decoder* LookupInternedMessage(uint64_t iid);
+
+ // Returns |nullptr| if no defaults were set in the given generation.
+ InternedMessageView* GetTracePacketDefaultsView() {
+ if (!trace_packet_defaults_)
+ return nullptr;
+ return &trace_packet_defaults_.value();
+ }
+
+ // Returns |nullptr| if no defaults were set in the given generation.
+ typename protos::pbzero::TracePacketDefaults::Decoder*
+ GetTracePacketDefaults() {
+ InternedMessageView* view = GetTracePacketDefaultsView();
+ if (!view)
+ return nullptr;
+ return view->GetOrCreateDecoder<protos::pbzero::TracePacketDefaults>();
+ }
+
+ PacketSequenceState* state() const { return state_; }
+
+ private:
+ friend class PacketSequenceState;
+
+ PacketSequenceStateGeneration(PacketSequenceState* state,
+ size_t generation_index)
+ : state_(state), generation_index_(generation_index) {}
+
+ PacketSequenceStateGeneration(PacketSequenceState* state,
+ size_t generation_index,
+ InternedFieldMap interned_data,
+ TraceBlobView defaults)
+ : state_(state),
+ generation_index_(generation_index),
+ interned_data_(interned_data),
+ trace_packet_defaults_(InternedMessageView(std::move(defaults))) {}
+
+ void InternMessage(uint32_t field_id, TraceBlobView message);
+
+ void SetTracePacketDefaults(TraceBlobView defaults) {
+ // Defaults should only be set once per generation.
+ PERFETTO_DCHECK(!trace_packet_defaults_);
+ trace_packet_defaults_ = InternedMessageView(std::move(defaults));
+ }
+
+ PacketSequenceState* state_;
+ size_t generation_index_;
+ InternedFieldMap interned_data_;
+ base::Optional<InternedMessageView> trace_packet_defaults_;
+};
+
class PacketSequenceState {
public:
- // Entry in an interning index, refers to the interned message.
- class InternedMessageView {
- public:
- InternedMessageView(TraceBlobView msg) : message_(std::move(msg)) {}
-
- InternedMessageView(InternedMessageView&&) noexcept = default;
- InternedMessageView& operator=(InternedMessageView&&) = default;
-
- // Allow copy by cloning the TraceBlobView. This is required for
- // UpdateTracePacketDefaults().
- InternedMessageView(const InternedMessageView& view)
- : message_(view.message_.slice(0, view.message_.length())) {}
- InternedMessageView& operator=(const InternedMessageView& view) {
- this->message_ = view.message_.slice(0, view.message_.length());
- this->decoder_ = nullptr;
- this->decoder_type_ = nullptr;
- this->submessages_.clear();
- return *this;
- }
-
- // Lazily initializes and returns the decoder object for the message. The
- // decoder is stored in the InternedMessageView to avoid having to parse the
- // message multiple times.
- template <typename MessageType>
- typename MessageType::Decoder* GetOrCreateDecoder() {
- if (!decoder_) {
- // Lazy init the decoder and save it away, so that we don't have to
- // reparse the message every time we access the interning entry.
- decoder_ = std::unique_ptr<void, std::function<void(void*)>>(
- new
- typename MessageType::Decoder(message_.data(), message_.length()),
- [](void* obj) {
- delete reinterpret_cast<typename MessageType::Decoder*>(obj);
- });
- decoder_type_ = PERFETTO_TYPE_IDENTIFIER;
- }
- // Verify that the type of the decoder didn't change.
- if (PERFETTO_TYPE_IDENTIFIER &&
- strcmp(decoder_type_,
- // GCC complains if this arg can be null.
- PERFETTO_TYPE_IDENTIFIER ? PERFETTO_TYPE_IDENTIFIER : "") !=
- 0) {
- PERFETTO_FATAL(
- "Interning entry accessed under different types! previous type: "
- "%s. new type: %s.",
- decoder_type_, __PRETTY_FUNCTION__);
- }
- return reinterpret_cast<typename MessageType::Decoder*>(decoder_.get());
- }
-
- // Lookup a submessage of the interned message, which is then itself stored
- // as InternedMessageView, so that we only need to parse it once. Returns
- // nullptr if the field isn't set.
- // TODO(eseckler): Support repeated fields.
- template <typename MessageType, uint32_t FieldId>
- InternedMessageView* GetOrCreateSubmessageView() {
- auto it = submessages_.find(FieldId);
- if (it != submessages_.end())
- return it->second.get();
- auto* decoder = GetOrCreateDecoder<MessageType>();
- // Calls the at() template method on the decoder.
- auto field = decoder->template at<FieldId>().as_bytes();
- if (!field.data)
- return nullptr;
- const size_t offset = message_.offset_of(field.data);
- TraceBlobView submessage = message_.slice(offset, field.size);
- InternedMessageView* submessage_view =
- new InternedMessageView(std::move(submessage));
- submessages_.emplace_hint(
- it, FieldId, std::unique_ptr<InternedMessageView>(submessage_view));
- return submessage_view;
- }
-
- const TraceBlobView& message() { return message_; }
-
- private:
- using SubMessageViewMap =
- std::unordered_map<uint32_t /*field_id*/,
- std::unique_ptr<InternedMessageView>>;
-
- TraceBlobView message_;
-
- // Stores the decoder for the message_, so that the message does not have to
- // be re-decoded every time the interned message is looked up. Lazily
- // initialized in GetOrCreateDecoder(). Since we don't know the type of the
- // decoder until GetOrCreateDecoder() is called, we store the decoder as a
- // void* unique_pointer with a destructor function that's supplied in
- // GetOrCreateDecoder() when the decoder is created.
- std::unique_ptr<void, std::function<void(void*)>> decoder_;
-
- // Type identifier for the decoder. Only valid in debug builds and on
- // supported platforms. Used to verify that GetOrCreateDecoder() is always
- // called with the same template argument.
- const char* decoder_type_ = nullptr;
-
- // Views of submessages of the interned message. Submessages are lazily
- // added by GetOrCreateSubmessageView(). By storing submessages and their
- // decoders, we avoid having to decode submessages multiple times if they
- // looked up often.
- SubMessageViewMap submessages_;
- };
-
- using InternedMessageMap =
- std::unordered_map<uint64_t /*iid*/, InternedMessageView>;
- using InternedFieldMap =
- std::unordered_map<uint32_t /*field_id*/, InternedMessageMap>;
-
- struct GenerationData {
- InternedFieldMap interned_data;
- base::Optional<InternedMessageView> trace_packet_defaults;
- };
-
- // TODO(eseckler): Reference count the generations so that we can get rid of
- // past generations once all packets referring to them have been parsed.
- using GenerationList = std::vector<GenerationData>;
-
PacketSequenceState(TraceProcessorContext* context)
: context_(context), stack_profile_tracker_(context) {
- generations_.emplace_back();
+ generations_.emplace_back(
+ new PacketSequenceStateGeneration(this, generations_.size()));
}
int64_t IncrementAndGetTrackEventTimeNs(int64_t delta_ns) {
@@ -183,14 +230,26 @@
return track_event_thread_instruction_count_;
}
- void OnPacketLoss() {
- packet_loss_ = true;
- track_event_timestamps_valid_ = false;
+ // Intern a message into the current generation.
+ void InternMessage(uint32_t field_id, TraceBlobView message) {
+ generations_.back()->InternMessage(field_id, std::move(message));
}
- void OnIncrementalStateCleared() {
- packet_loss_ = false;
- generations_.emplace_back(); // Bump generation number
+ // Set the trace packet defaults for the current generation. If the current
+ // generation already has defaults set, starts a new generation without
+ // invalidating other incremental state (such as interned data).
+ void UpdateTracePacketDefaults(TraceBlobView defaults) {
+ if (!generations_.back()->GetTracePacketDefaultsView()) {
+ generations_.back()->SetTracePacketDefaults(std::move(defaults));
+ return;
+ }
+
+ // The new defaults should only apply to subsequent messages on the
+ // sequence. Add a new generation with the updated defaults but the
+ // current generation's interned data state.
+ generations_.emplace_back(new PacketSequenceStateGeneration(
+ this, generations_.size(), generations_.back()->interned_data_,
+ std::move(defaults)));
}
void SetThreadDescriptor(int32_t pid,
@@ -207,14 +266,28 @@
track_event_thread_instruction_count_ = thread_instruction_count;
}
+ void OnPacketLoss() {
+ packet_loss_ = true;
+ track_event_timestamps_valid_ = false;
+ }
+
+ // Starts a new generation with clean-slate incremental state and defaults.
+ void OnIncrementalStateCleared() {
+ packet_loss_ = false;
+ generations_.emplace_back(
+ new PacketSequenceStateGeneration(this, generations_.size()));
+ }
+
bool IsIncrementalStateValid() const { return !packet_loss_; }
StackProfileTracker& stack_profile_tracker() {
return stack_profile_tracker_;
}
- // Returns the index of the current generation in the GenerationList.
- size_t current_generation() const { return generations_.size() - 1; }
+ // Returns a pointer to the current generation.
+ PacketSequenceStateGeneration* current_generation() const {
+ return generations_.back().get();
+ }
bool track_event_timestamps_valid() const {
return track_event_timestamps_valid_;
@@ -225,90 +298,14 @@
int32_t pid() const { return pid_; }
int32_t tid() const { return tid_; }
- void InternMessage(uint32_t field_id, TraceBlobView message) {
- constexpr auto kIidFieldNumber = 1;
-
- uint64_t iid = 0;
- auto message_start = message.data();
- auto message_size = message.length();
- protozero::ProtoDecoder decoder(message_start, message_size);
-
- auto field = decoder.FindField(kIidFieldNumber);
- if (PERFETTO_UNLIKELY(!field)) {
- PERFETTO_DLOG("Interned message without interning_id");
- context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
- return;
- }
- iid = field.as_uint64();
-
- auto* map = &generations_.back().interned_data[field_id];
- auto res = map->emplace(iid, InternedMessageView(std::move(message)));
-
- // If a message with this ID is already interned in the same generation,
- // its data should not have changed (this is forbidden by the InternedData
- // proto).
- // TODO(eseckler): This DCHECK assumes that the message is encoded the
- // same way if it is re-emitted.
- PERFETTO_DCHECK(res.second ||
- (res.first->second.message().length() == message_size &&
- memcmp(res.first->second.message().data(), message_start,
- message_size) == 0));
- }
-
- // Returns |nullptr| if the message with the given |iid| was not found (also
- // records a stat in this case).
- template <uint32_t FieldId, typename MessageType>
- typename MessageType::Decoder* LookupInternedMessage(size_t generation,
- uint64_t iid) {
- PERFETTO_CHECK(generation <= generations_.size());
- auto* field_map = &generations_[generation].interned_data;
- auto field_it = field_map->find(FieldId);
- if (field_it != field_map->end()) {
- auto* message_map = &field_it->second;
- auto it = message_map->find(iid);
- if (it != message_map->end()) {
- return it->second.GetOrCreateDecoder<MessageType>();
- }
- }
- context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
- PERFETTO_DLOG("Could not find interning entry for field ID %" PRIu32
- ", generation %zu, and IID %" PRIu64,
- FieldId, generation, iid);
- return nullptr;
- }
-
- void UpdateTracePacketDefaults(TraceBlobView trace_packet_defaults) {
- if (generations_.back().trace_packet_defaults) {
- // The new defaults should only apply to subsequent messages on the
- // sequence. Add a new generation with the updated defaults but the
- // current generation's interned data state.
- const InternedFieldMap& current_interned_data =
- generations_.back().interned_data;
- generations_.emplace_back();
- generations_.back().interned_data = current_interned_data;
- }
- generations_.back().trace_packet_defaults =
- InternedMessageView(std::move(trace_packet_defaults));
- }
-
- // Returns |nullptr| if no defaults were set in the given generation.
- InternedMessageView* GetTracePacketDefaultsView(size_t generation) {
- PERFETTO_CHECK(generation <= generations_.size());
- if (!generations_[generation].trace_packet_defaults)
- return nullptr;
- return &generations_[generation].trace_packet_defaults.value();
- }
-
- // Returns |nullptr| if no defaults were set in the given generation.
- typename protos::pbzero::TracePacketDefaults::Decoder* GetTracePacketDefaults(
- size_t generation) {
- InternedMessageView* view = GetTracePacketDefaultsView(generation);
- if (!view)
- return nullptr;
- return view->GetOrCreateDecoder<protos::pbzero::TracePacketDefaults>();
- }
+ TraceProcessorContext* context() const { return context_; }
private:
+ // TODO(eseckler): Reference count the generations so that we can get rid of
+ // past generations once all packets referring to them have been parsed.
+ using GenerationList =
+ std::vector<std::unique_ptr<PacketSequenceStateGeneration>>;
+
TraceProcessorContext* context_;
// If true, incremental state on the sequence is considered invalid until we
@@ -340,6 +337,25 @@
StackProfileTracker stack_profile_tracker_;
};
+template <uint32_t FieldId, typename MessageType>
+typename MessageType::Decoder*
+PacketSequenceStateGeneration::LookupInternedMessage(uint64_t iid) {
+ auto field_it = interned_data_.find(FieldId);
+ if (field_it != interned_data_.end()) {
+ auto* message_map = &field_it->second;
+ auto it = message_map->find(iid);
+ if (it != message_map->end()) {
+ return it->second.GetOrCreateDecoder<MessageType>();
+ }
+ }
+ state_->context()->storage->IncrementStats(
+ stats::interned_data_tokenizer_errors);
+ PERFETTO_DLOG("Could not find interning entry for field ID %" PRIu32
+ ", generation %zu, and IID %" PRIu64,
+ FieldId, generation_index_, iid);
+ return nullptr;
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index eb32e46..66def9e 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -95,9 +95,8 @@
class ProfilePacketInternLookup : public StackProfileTracker::InternLookup {
public:
- ProfilePacketInternLookup(PacketSequenceState* seq_state,
- size_t seq_state_generation)
- : seq_state_(seq_state), seq_state_generation_(seq_state_generation) {}
+ ProfilePacketInternLookup(PacketSequenceStateGeneration* seq_state)
+ : seq_state_(seq_state) {}
base::Optional<base::StringView> GetString(
StackProfileTracker::SourceStringId iid,
@@ -107,17 +106,17 @@
case StackProfileTracker::InternedStringType::kBuildId:
decoder = seq_state_->LookupInternedMessage<
protos::pbzero::InternedData::kBuildIdsFieldNumber,
- protos::pbzero::InternedString>(seq_state_generation_, iid);
+ protos::pbzero::InternedString>(iid);
break;
case StackProfileTracker::InternedStringType::kFunctionName:
decoder = seq_state_->LookupInternedMessage<
protos::pbzero::InternedData::kFunctionNamesFieldNumber,
- protos::pbzero::InternedString>(seq_state_generation_, iid);
+ protos::pbzero::InternedString>(iid);
break;
case StackProfileTracker::InternedStringType::kMappingPath:
decoder = seq_state_->LookupInternedMessage<
protos::pbzero::InternedData::kMappingPathsFieldNumber,
- protos::pbzero::InternedString>(seq_state_generation_, iid);
+ protos::pbzero::InternedString>(iid);
break;
}
if (!decoder)
@@ -130,7 +129,7 @@
StackProfileTracker::SourceMappingId iid) const override {
auto* decoder = seq_state_->LookupInternedMessage<
protos::pbzero::InternedData::kMappingsFieldNumber,
- protos::pbzero::Mapping>(seq_state_generation_, iid);
+ protos::pbzero::Mapping>(iid);
if (!decoder)
return base::nullopt;
return MakeSourceMapping(*decoder);
@@ -140,7 +139,7 @@
StackProfileTracker::SourceFrameId iid) const override {
auto* decoder = seq_state_->LookupInternedMessage<
protos::pbzero::InternedData::kFramesFieldNumber,
- protos::pbzero::Frame>(seq_state_generation_, iid);
+ protos::pbzero::Frame>(iid);
if (!decoder)
return base::nullopt;
return MakeSourceFrame(*decoder);
@@ -150,15 +149,14 @@
StackProfileTracker::SourceCallstackId iid) const override {
auto* decoder = seq_state_->LookupInternedMessage<
protos::pbzero::InternedData::kCallstacksFieldNumber,
- protos::pbzero::Callstack>(seq_state_generation_, iid);
+ protos::pbzero::Callstack>(iid);
if (!decoder)
return base::nullopt;
return MakeSourceCallstack(*decoder);
}
private:
- PacketSequenceState* seq_state_;
- size_t seq_state_generation_;
+ PacketSequenceStateGeneration* seq_state_;
};
} // namespace
@@ -219,14 +217,13 @@
ParseTraceStats(packet.trace_stats());
if (packet.has_profile_packet()) {
- ParseProfilePacket(
- ts, data->packet_sequence_state, data->packet_sequence_state_generation,
- packet.trusted_packet_sequence_id(), packet.profile_packet());
+ ParseProfilePacket(ts, data->sequence_state,
+ packet.trusted_packet_sequence_id(),
+ packet.profile_packet());
}
if (packet.has_streaming_profile_packet()) {
- ParseStreamingProfilePacket(data->packet_sequence_state,
- data->packet_sequence_state_generation,
+ ParseStreamingProfilePacket(data->sequence_state,
packet.streaming_profile_packet());
}
@@ -328,11 +325,11 @@
}
}
-void ProtoTraceParser::ParseProfilePacket(int64_t,
- PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
- uint32_t seq_id,
- ConstBytes blob) {
+void ProtoTraceParser::ParseProfilePacket(
+ int64_t,
+ PacketSequenceStateGeneration* sequence_state,
+ uint32_t seq_id,
+ ConstBytes blob) {
protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
context_->heap_profile_tracker->SetProfilePacketIndex(seq_id, packet.index());
@@ -341,28 +338,30 @@
const char* str = reinterpret_cast<const char*>(entry.str().data);
auto str_view = base::StringView(str, entry.str().size);
- sequence_state->stack_profile_tracker().AddString(entry.iid(), str_view);
+ sequence_state->state()->stack_profile_tracker().AddString(entry.iid(),
+ str_view);
}
for (auto it = packet.mappings(); it; ++it) {
protos::pbzero::Mapping::Decoder entry(*it);
StackProfileTracker::SourceMapping src_mapping = MakeSourceMapping(entry);
- sequence_state->stack_profile_tracker().AddMapping(entry.iid(),
- src_mapping);
+ sequence_state->state()->stack_profile_tracker().AddMapping(entry.iid(),
+ src_mapping);
}
for (auto it = packet.frames(); it; ++it) {
protos::pbzero::Frame::Decoder entry(*it);
StackProfileTracker::SourceFrame src_frame = MakeSourceFrame(entry);
- sequence_state->stack_profile_tracker().AddFrame(entry.iid(), src_frame);
+ sequence_state->state()->stack_profile_tracker().AddFrame(entry.iid(),
+ src_frame);
}
for (auto it = packet.callstacks(); it; ++it) {
protos::pbzero::Callstack::Decoder entry(*it);
StackProfileTracker::SourceCallstack src_callstack =
MakeSourceCallstack(entry);
- sequence_state->stack_profile_tracker().AddCallstack(entry.iid(),
- src_callstack);
+ sequence_state->state()->stack_profile_tracker().AddCallstack(
+ entry.iid(), src_callstack);
}
for (auto it = packet.process_dumps(); it; ++it) {
@@ -412,28 +411,26 @@
}
if (!packet.continued()) {
PERFETTO_CHECK(sequence_state);
- ProfilePacketInternLookup intern_lookup(sequence_state,
- sequence_state_generation);
+ ProfilePacketInternLookup intern_lookup(sequence_state);
context_->heap_profile_tracker->FinalizeProfile(
- seq_id, &sequence_state->stack_profile_tracker(), &intern_lookup);
+ seq_id, &sequence_state->state()->stack_profile_tracker(),
+ &intern_lookup);
}
}
void ProtoTraceParser::ParseStreamingProfilePacket(
- PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration* sequence_state,
ConstBytes blob) {
protos::pbzero::StreamingProfilePacket::Decoder packet(blob.data, blob.size);
ProcessTracker* procs = context_->process_tracker.get();
TraceStorage* storage = context_->storage.get();
StackProfileTracker& stack_profile_tracker =
- sequence_state->stack_profile_tracker();
- ProfilePacketInternLookup intern_lookup(sequence_state,
- sequence_state_generation);
+ sequence_state->state()->stack_profile_tracker();
+ ProfilePacketInternLookup intern_lookup(sequence_state);
- uint32_t pid = static_cast<uint32_t>(sequence_state->pid());
- uint32_t tid = static_cast<uint32_t>(sequence_state->tid());
+ uint32_t pid = static_cast<uint32_t>(sequence_state->state()->pid());
+ uint32_t tid = static_cast<uint32_t>(sequence_state->state()->tid());
UniqueTid utid = procs->UpdateThread(tid, pid);
auto timestamp_it = packet.timestamp_delta_us();
@@ -457,7 +454,7 @@
int64_t callstack_id = *maybe_callstack_id;
tables::CpuProfileStackSampleTable::Row sample_row{
- sequence_state->IncrementAndGetTrackEventTimeNs(*timestamp_it),
+ sequence_state->state()->IncrementAndGetTrackEventTimeNs(*timestamp_it),
callstack_id, utid};
storage->mutable_cpu_profile_stack_sample_table()->Insert(sample_row);
}
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.h b/src/trace_processor/importers/proto/proto_trace_parser.h
index 25b4367..9e20b3e 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.h
+++ b/src/trace_processor/importers/proto/proto_trace_parser.h
@@ -63,13 +63,10 @@
void ParseTraceStats(ConstBytes);
void ParseProfilePacket(int64_t ts,
- PacketSequenceState*,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration*,
uint32_t seq_id,
ConstBytes);
- void ParseStreamingProfilePacket(PacketSequenceState*,
- size_t sequence_state_generation,
- ConstBytes);
+ void ParseStreamingProfilePacket(PacketSequenceStateGeneration*, ConstBytes);
void ParseChromeBenchmarkMetadata(ConstBytes);
void ParseChromeEvents(int64_t ts, ConstBytes);
void ParseMetatraceEvent(int64_t ts, ConstBytes);
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
index 8ac2b36..b964a2c 100644
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
+++ b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
@@ -234,7 +234,7 @@
}
protos::pbzero::TracePacketDefaults::Decoder* defaults =
- state->GetTracePacketDefaults(state->current_generation());
+ state->current_generation()->GetTracePacketDefaults();
int64_t timestamp;
if (decoder.has_timestamp()) {
diff --git a/src/trace_processor/importers/proto/track_event_module.cc b/src/trace_processor/importers/proto/track_event_module.cc
index a96cf53..c731fcc 100644
--- a/src/trace_processor/importers/proto/track_event_module.cc
+++ b/src/trace_processor/importers/proto/track_event_module.cc
@@ -69,9 +69,7 @@
parser_.ParseTrackEvent(
ttp.timestamp, ttp.track_event_data->thread_timestamp,
ttp.track_event_data->thread_instruction_count,
- ttp.track_event_data->packet_sequence_state,
- ttp.track_event_data->packet_sequence_state_generation,
- decoder.track_event());
+ ttp.track_event_data->sequence_state, decoder.track_event());
}
}
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index 37d47a0..c496eae 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -65,8 +65,7 @@
ArgsTracker::BoundInserter* inserter) {
auto* decoder = state.sequence_state->LookupInternedMessage<
protos::pbzero::InternedData::kSourceLocationsFieldNumber,
- protos::pbzero::SourceLocation>(state.sequence_generation,
- field.as_uint64());
+ protos::pbzero::SourceLocation>(field.as_uint64());
if (!decoder) {
// Lookup failed fall back on default behaviour which will just put
// the source_location_iid into the args table.
@@ -194,17 +193,16 @@
context->storage->InternString("SUBRESOURCE_FILTER"),
context->storage->InternString("UNFREEZABLE_FRAME")}} {}
-void TrackEventParser::ParseTrackEvent(int64_t ts,
- int64_t tts,
- int64_t ticount,
- PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
- ConstBytes blob) {
+void TrackEventParser::ParseTrackEvent(
+ int64_t ts,
+ int64_t tts,
+ int64_t ticount,
+ PacketSequenceStateGeneration* sequence_state,
+ ConstBytes blob) {
using LegacyEvent = protos::pbzero::TrackEvent::LegacyEvent;
protos::pbzero::TrackEventDefaults::Decoder* defaults = nullptr;
- auto* packet_defaults_view =
- sequence_state->GetTracePacketDefaultsView(sequence_state_generation);
+ auto* packet_defaults_view = sequence_state->GetTracePacketDefaultsView();
if (packet_defaults_view) {
auto* track_event_defaults_view =
packet_defaults_view
@@ -252,8 +250,7 @@
if (PERFETTO_LIKELY(category_iids.size() == 1 && category_strings.empty())) {
auto* decoder = sequence_state->LookupInternedMessage<
protos::pbzero::InternedData::kEventCategoriesFieldNumber,
- protos::pbzero::EventCategory>(sequence_state_generation,
- category_iids[0]);
+ protos::pbzero::EventCategory>(category_iids[0]);
if (decoder)
category_id = storage->InternString(decoder->name());
} else if (category_iids.empty() && category_strings.size() == 1) {
@@ -266,7 +263,7 @@
for (uint64_t iid : category_iids) {
auto* decoder = sequence_state->LookupInternedMessage<
protos::pbzero::InternedData::kEventCategoriesFieldNumber,
- protos::pbzero::EventCategory>(sequence_state_generation, iid);
+ protos::pbzero::EventCategory>(iid);
if (!decoder)
continue;
base::StringView name = decoder->name();
@@ -292,7 +289,7 @@
if (PERFETTO_LIKELY(name_iid)) {
auto* decoder = sequence_state->LookupInternedMessage<
protos::pbzero::InternedData::kEventNamesFieldNumber,
- protos::pbzero::EventName>(sequence_state_generation, name_iid);
+ protos::pbzero::EventName>(name_iid);
if (decoder)
name_id = storage->InternString(decoder->name());
} else if (event.has_name()) {
@@ -337,11 +334,11 @@
if (process_track_row)
upid = storage->process_track_table().upid()[*process_track_row];
}
- } else if (sequence_state->pid_and_tid_valid() ||
+ } else if (sequence_state->state()->pid_and_tid_valid() ||
(legacy_event.has_pid_override() &&
legacy_event.has_tid_override())) {
- uint32_t pid = static_cast<uint32_t>(sequence_state->pid());
- uint32_t tid = static_cast<uint32_t>(sequence_state->tid());
+ uint32_t pid = static_cast<uint32_t>(sequence_state->state()->pid());
+ uint32_t tid = static_cast<uint32_t>(sequence_state->state()->tid());
if (legacy_event.has_pid_override())
pid = static_cast<uint32_t>(legacy_event.pid_override());
if (legacy_event.has_tid_override())
@@ -467,26 +464,21 @@
}
}
- auto args_callback = [this, &event, &legacy_event, &sequence_state,
- sequence_state_generation, ts, utid,
+ auto args_callback = [this, &event, &legacy_event, sequence_state, ts, utid,
legacy_tid](ArgsTracker::BoundInserter* inserter) {
for (auto it = event.debug_annotations(); it; ++it) {
- ParseDebugAnnotationArgs(*it, sequence_state, sequence_state_generation,
- inserter);
+ ParseDebugAnnotationArgs(*it, sequence_state, inserter);
}
if (event.has_task_execution()) {
- ParseTaskExecutionArgs(event.task_execution(), sequence_state,
- sequence_state_generation, inserter);
+ ParseTaskExecutionArgs(event.task_execution(), sequence_state, inserter);
}
if (event.has_log_message()) {
- ParseLogMessage(event.log_message(), sequence_state,
- sequence_state_generation, ts, utid, inserter);
+ ParseLogMessage(event.log_message(), sequence_state, ts, utid, inserter);
}
if (event.has_cc_scheduler_state()) {
- ParseCcScheduler(event.cc_scheduler_state(), sequence_state,
- sequence_state_generation, inserter);
+ ParseCcScheduler(event.cc_scheduler_state(), sequence_state, inserter);
}
if (event.has_chrome_user_event()) {
ParseChromeUserEvent(event.chrome_user_event(), inserter);
@@ -831,8 +823,7 @@
void TrackEventParser::ParseDebugAnnotationArgs(
ConstBytes debug_annotation,
- PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration* sequence_state,
ArgsTracker::BoundInserter* inserter) {
TraceStorage* storage = context_->storage.get();
@@ -845,8 +836,7 @@
if (PERFETTO_LIKELY(name_iid)) {
auto* decoder = sequence_state->LookupInternedMessage<
protos::pbzero::InternedData::kDebugAnnotationNamesFieldNumber,
- protos::pbzero::DebugAnnotationName>(sequence_state_generation,
- name_iid);
+ protos::pbzero::DebugAnnotationName>(name_iid);
if (!decoder)
return;
@@ -942,8 +932,7 @@
void TrackEventParser::ParseTaskExecutionArgs(
ConstBytes task_execution,
- PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration* sequence_state,
ArgsTracker::BoundInserter* inserter) {
protos::pbzero::TaskExecution::Decoder task(task_execution.data,
task_execution.size);
@@ -953,7 +942,7 @@
auto* decoder = sequence_state->LookupInternedMessage<
protos::pbzero::InternedData::kSourceLocationsFieldNumber,
- protos::pbzero::SourceLocation>(sequence_state_generation, iid);
+ protos::pbzero::SourceLocation>(iid);
if (!decoder)
return;
@@ -974,12 +963,12 @@
Variadic::UnsignedInteger(line_number));
}
-void TrackEventParser::ParseLogMessage(ConstBytes blob,
- PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
- int64_t ts,
- base::Optional<UniqueTid> utid,
- ArgsTracker::BoundInserter* inserter) {
+void TrackEventParser::ParseLogMessage(
+ ConstBytes blob,
+ PacketSequenceStateGeneration* sequence_state,
+ int64_t ts,
+ base::Optional<UniqueTid> utid,
+ ArgsTracker::BoundInserter* inserter) {
if (!utid) {
context_->storage->IncrementStats(stats::track_event_parser_errors);
PERFETTO_DLOG("LogMessage without thread association");
@@ -994,8 +983,7 @@
auto* decoder = sequence_state->LookupInternedMessage<
protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
- protos::pbzero::LogMessageBody>(sequence_state_generation,
- message.body_iid());
+ protos::pbzero::LogMessageBody>(message.body_iid());
if (!decoder)
return;
@@ -1016,13 +1004,12 @@
void TrackEventParser::ParseCcScheduler(
ConstBytes cc,
- PacketSequenceState* sequence_state,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration* sequence_state,
ArgsTracker::BoundInserter* outer_inserter) {
// The 79 decides the initial amount of memory reserved in the prefix. This
// was determined my manually counting the length of the longest column.
constexpr size_t kCcSchedulerStateMaxColumnLength = 79;
- ProtoToArgsTable helper(sequence_state, sequence_state_generation, context_,
+ ProtoToArgsTable helper(sequence_state, context_,
/* starting_prefix = */ "",
kCcSchedulerStateMaxColumnLength);
auto status = helper.AddProtoFileDescriptor(
diff --git a/src/trace_processor/importers/proto/track_event_parser.h b/src/trace_processor/importers/proto/track_event_parser.h
index 8a847d2..a0a42c7 100644
--- a/src/trace_processor/importers/proto/track_event_parser.h
+++ b/src/trace_processor/importers/proto/track_event_parser.h
@@ -32,7 +32,7 @@
namespace trace_processor {
-class PacketSequenceState;
+class PacketSequenceStateGeneration;
class TraceProcessorContext;
class TrackEventParser {
@@ -42,8 +42,7 @@
void ParseTrackEvent(int64_t ts,
int64_t tts,
int64_t ticount,
- PacketSequenceState*,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration*,
protozero::ConstBytes);
void ParseLegacyEventAsRawEvent(
int64_t ts,
@@ -55,26 +54,22 @@
const protos::pbzero::TrackEvent_LegacyEvent_Decoder& legacy_event,
SliceTracker::SetArgsCallback slice_args_callback);
void ParseDebugAnnotationArgs(protozero::ConstBytes debug_annotation,
- PacketSequenceState*,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration*,
ArgsTracker::BoundInserter* inserter);
void ParseNestedValueArgs(protozero::ConstBytes nested_value,
base::StringView flat_key,
base::StringView key,
ArgsTracker::BoundInserter* inserter);
void ParseTaskExecutionArgs(protozero::ConstBytes task_execution,
- PacketSequenceState*,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration*,
ArgsTracker::BoundInserter* inserter);
void ParseLogMessage(protozero::ConstBytes,
- PacketSequenceState*,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration*,
int64_t,
base::Optional<UniqueTid>,
ArgsTracker::BoundInserter* inserter);
void ParseCcScheduler(protozero::ConstBytes cc_scheduler,
- PacketSequenceState*,
- size_t sequence_state_generation,
+ PacketSequenceStateGeneration*,
ArgsTracker::BoundInserter* inserter);
void ParseChromeUserEvent(protozero::ConstBytes chrome_user_event,
ArgsTracker::BoundInserter* inserter);
diff --git a/src/trace_processor/importers/proto/vulkan_memory_tracker.h b/src/trace_processor/importers/proto/vulkan_memory_tracker.h
index f3b8e16..e437717 100644
--- a/src/trace_processor/importers/proto/vulkan_memory_tracker.h
+++ b/src/trace_processor/importers/proto/vulkan_memory_tracker.h
@@ -40,12 +40,11 @@
~VulkanMemoryTracker() = default;
template <int32_t FieldId>
- StringId GetInternedString(PacketSequenceState* state,
- size_t generation,
+ StringId GetInternedString(PacketSequenceStateGeneration* state,
uint64_t iid) {
auto* decoder =
state->LookupInternedMessage<FieldId, protos::pbzero::InternedString>(
- generation, iid);
+ iid);
if (!decoder)
return kNullStringId;
return context_->storage->InternString(
diff --git a/src/trace_processor/timestamped_trace_piece.h b/src/trace_processor/timestamped_trace_piece.h
index 464864c..2414f89 100644
--- a/src/trace_processor/timestamped_trace_piece.h
+++ b/src/trace_processor/timestamped_trace_piece.h
@@ -63,18 +63,15 @@
struct TracePacketData {
TraceBlobView packet;
- // TODO(eseckler): Refactor this into a single pointer to a PSSGeneration.
- PacketSequenceState* packet_sequence_state;
- size_t packet_sequence_state_generation;
+ PacketSequenceStateGeneration* sequence_state;
};
struct TrackEventData : public TracePacketData {
TrackEventData(TraceBlobView pv,
- PacketSequenceState* pss,
- size_t pss_generation,
+ PacketSequenceStateGeneration* generation,
int64_t thread_ts,
int64_t thread_ic)
- : TracePacketData{std::move(pv), pss, pss_generation},
+ : TracePacketData{std::move(pv), generation},
thread_timestamp(thread_ts),
thread_instruction_count(thread_ic) {}
@@ -99,9 +96,8 @@
TimestampedTracePiece(int64_t ts,
uint64_t idx,
TraceBlobView tbv,
- PacketSequenceState* sequence_state)
- : packet_data{std::move(tbv), sequence_state,
- sequence_state ? sequence_state->current_generation() : 0},
+ PacketSequenceStateGeneration* sequence_state)
+ : packet_data{std::move(tbv), sequence_state},
timestamp(ts),
packet_idx(idx),
type(Type::kTracePacket) {}
diff --git a/src/trace_processor/trace_sorter.h b/src/trace_processor/trace_sorter.h
index 0b8502a..b1ccf56 100644
--- a/src/trace_processor/trace_sorter.h
+++ b/src/trace_processor/trace_sorter.h
@@ -73,7 +73,8 @@
DCHECK_ftrace_batch_cpu(kNoBatch);
auto* queue = GetQueue(0);
queue->Append(TimestampedTracePiece(timestamp, packet_idx_++,
- std::move(packet), state));
+ std::move(packet),
+ state->current_generation()));
MaybeExtractEvents(queue);
}
@@ -135,9 +136,9 @@
PacketSequenceState* state,
TraceBlobView packet) {
auto* queue = GetQueue(0);
- std::unique_ptr<TrackEventData> data(new TrackEventData{
- std::move(packet), state, state->current_generation(), thread_time,
- thread_instruction_count});
+ std::unique_ptr<TrackEventData> data(
+ new TrackEventData{std::move(packet), state->current_generation(),
+ thread_time, thread_instruction_count});
queue->Append(
TimestampedTracePiece(timestamp, packet_idx_++, std::move(data)));
MaybeExtractEvents(queue);
diff --git a/src/trace_processor/trace_sorter_unittest.cc b/src/trace_processor/trace_sorter_unittest.cc
index 8f4ea0b..5db7c0f 100644
--- a/src/trace_processor/trace_sorter_unittest.cc
+++ b/src/trace_processor/trace_sorter_unittest.cc
@@ -99,14 +99,16 @@
}
TEST_F(TraceSorterTest, TestTracePacket) {
+ PacketSequenceState state(&context_);
TraceBlobView view = test_buffer_.slice(0, 1);
EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1000, view.data(), 1));
- context_.sorter->PushTracePacket(1000, nullptr, std::move(view));
+ context_.sorter->PushTracePacket(1000, &state, std::move(view));
context_.sorter->FinalizeFtraceEventBatch(1000);
context_.sorter->ExtractEventsForced();
}
TEST_F(TraceSorterTest, Ordering) {
+ PacketSequenceState state(&context_);
TraceBlobView view_1 = test_buffer_.slice(0, 1);
TraceBlobView view_2 = test_buffer_.slice(0, 2);
TraceBlobView view_3 = test_buffer_.slice(0, 3);
@@ -123,8 +125,8 @@
context_.sorter->PushFtraceEvent(2 /*cpu*/, 1200 /*timestamp*/,
std::move(view_4));
context_.sorter->FinalizeFtraceEventBatch(2);
- context_.sorter->PushTracePacket(1001, nullptr, std::move(view_2));
- context_.sorter->PushTracePacket(1100, nullptr, std::move(view_3));
+ context_.sorter->PushTracePacket(1001, &state, std::move(view_2));
+ context_.sorter->PushTracePacket(1100, &state, std::move(view_3));
context_.sorter->PushFtraceEvent(0 /*cpu*/, 1000 /*timestamp*/,
std::move(view_1));
@@ -133,6 +135,7 @@
}
TEST_F(TraceSorterTest, SetWindowSize) {
+ PacketSequenceState state(&context_);
TraceBlobView view_1 = test_buffer_.slice(0, 1);
TraceBlobView view_2 = test_buffer_.slice(0, 2);
TraceBlobView view_3 = test_buffer_.slice(0, 3);
@@ -155,8 +158,8 @@
context_.sorter->PushFtraceEvent(2 /*cpu*/, 1200 /*timestamp*/,
std::move(view_4));
context_.sorter->FinalizeFtraceEventBatch(2);
- context_.sorter->PushTracePacket(1001, nullptr, std::move(view_2));
- context_.sorter->PushTracePacket(1100, nullptr, std::move(view_3));
+ context_.sorter->PushTracePacket(1001, &state, std::move(view_2));
+ context_.sorter->PushTracePacket(1100, &state, std::move(view_3));
context_.sorter->PushFtraceEvent(0 /*cpu*/, 1000 /*timestamp*/,
std::move(view_1));