1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PACKET_SEQUENCE_STATE_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PACKET_SEQUENCE_STATE_H_
19
20 #include <stdint.h>
21
22 #include <unordered_map>
23 #include <vector>
24
25 #include "perfetto/base/compiler.h"
26 #include "perfetto/protozero/proto_decoder.h"
27 #include "perfetto/trace_processor/ref_counted.h"
28 #include "perfetto/trace_processor/trace_blob_view.h"
29 #include "src/trace_processor/importers/proto/stack_profile_tracker.h"
30 #include "src/trace_processor/storage/trace_storage.h"
31 #include "src/trace_processor/types/trace_processor_context.h"
32 #include "src/trace_processor/util/interned_message_view.h"
33
34 #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
35 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
36
37 namespace perfetto {
38 namespace trace_processor {
39
40 using InternedMessageMap =
41 std::unordered_map<uint64_t /*iid*/, InternedMessageView>;
42 using InternedFieldMap =
43 std::unordered_map<uint32_t /*field_id*/, InternedMessageMap>;
44
45 class PacketSequenceState;
46
47 class PacketSequenceStateGeneration : public RefCounted {
48 public:
49 // Returns |nullptr| if the message with the given |iid| was not found (also
50 // records a stat in this case).
51 template <uint32_t FieldId, typename MessageType>
52 typename MessageType::Decoder* LookupInternedMessage(uint64_t iid);
53
54 InternedMessageView* GetInternedMessageView(uint32_t field_id, uint64_t iid);
55 // Returns |nullptr| if no defaults were set.
GetTracePacketDefaultsView()56 InternedMessageView* GetTracePacketDefaultsView() {
57 if (!trace_packet_defaults_)
58 return nullptr;
59 return &trace_packet_defaults_.value();
60 }
61
62 // Returns |nullptr| if no defaults were set.
GetTracePacketDefaults()63 protos::pbzero::TracePacketDefaults::Decoder* GetTracePacketDefaults() {
64 InternedMessageView* view = GetTracePacketDefaultsView();
65 if (!view)
66 return nullptr;
67 return view->GetOrCreateDecoder<protos::pbzero::TracePacketDefaults>();
68 }
69
70 // Returns |nullptr| if no TrackEventDefaults were set.
GetTrackEventDefaults()71 protos::pbzero::TrackEventDefaults::Decoder* GetTrackEventDefaults() {
72 auto* packet_defaults_view = GetTracePacketDefaultsView();
73 if (packet_defaults_view) {
74 auto* track_event_defaults_view =
75 packet_defaults_view
76 ->GetOrCreateSubmessageView<protos::pbzero::TracePacketDefaults,
77 protos::pbzero::TracePacketDefaults::
78 kTrackEventDefaultsFieldNumber>();
79 if (track_event_defaults_view) {
80 return track_event_defaults_view
81 ->GetOrCreateDecoder<protos::pbzero::TrackEventDefaults>();
82 }
83 }
84 return nullptr;
85 }
86
state()87 PacketSequenceState* state() const { return state_; }
generation_index()88 size_t generation_index() const { return generation_index_; }
89
90 private:
91 friend class PacketSequenceState;
92
PacketSequenceStateGeneration(PacketSequenceState * state,size_t generation_index)93 PacketSequenceStateGeneration(PacketSequenceState* state,
94 size_t generation_index)
95 : state_(state), generation_index_(generation_index) {}
96
PacketSequenceStateGeneration(PacketSequenceState * state,size_t generation_index,InternedFieldMap interned_data,TraceBlobView defaults)97 PacketSequenceStateGeneration(PacketSequenceState* state,
98 size_t generation_index,
99 InternedFieldMap interned_data,
100 TraceBlobView defaults)
101 : state_(state),
102 generation_index_(generation_index),
103 interned_data_(interned_data),
104 trace_packet_defaults_(InternedMessageView(std::move(defaults))) {}
105
106 void InternMessage(uint32_t field_id, TraceBlobView message);
107
SetTracePacketDefaults(TraceBlobView defaults)108 void SetTracePacketDefaults(TraceBlobView defaults) {
109 // Defaults should only be set once per generation.
110 PERFETTO_DCHECK(!trace_packet_defaults_);
111 trace_packet_defaults_ = InternedMessageView(std::move(defaults));
112 }
113
114 PacketSequenceState* state_;
115 size_t generation_index_;
116 InternedFieldMap interned_data_;
117 base::Optional<InternedMessageView> trace_packet_defaults_;
118 };
119
120 class PacketSequenceState {
121 public:
PacketSequenceState(TraceProcessorContext * context)122 explicit PacketSequenceState(TraceProcessorContext* context)
123 : context_(context), sequence_stack_profile_tracker_(context) {
124 current_generation_.reset(
125 new PacketSequenceStateGeneration(this, generation_index_++));
126 }
127
IncrementAndGetTrackEventTimeNs(int64_t delta_ns)128 int64_t IncrementAndGetTrackEventTimeNs(int64_t delta_ns) {
129 PERFETTO_DCHECK(track_event_timestamps_valid());
130 track_event_timestamp_ns_ += delta_ns;
131 return track_event_timestamp_ns_;
132 }
133
IncrementAndGetTrackEventThreadTimeNs(int64_t delta_ns)134 int64_t IncrementAndGetTrackEventThreadTimeNs(int64_t delta_ns) {
135 PERFETTO_DCHECK(track_event_timestamps_valid());
136 track_event_thread_timestamp_ns_ += delta_ns;
137 return track_event_thread_timestamp_ns_;
138 }
139
IncrementAndGetTrackEventThreadInstructionCount(int64_t delta)140 int64_t IncrementAndGetTrackEventThreadInstructionCount(int64_t delta) {
141 PERFETTO_DCHECK(track_event_timestamps_valid());
142 track_event_thread_instruction_count_ += delta;
143 return track_event_thread_instruction_count_;
144 }
145
146 // Intern a message into the current generation.
InternMessage(uint32_t field_id,TraceBlobView message)147 void InternMessage(uint32_t field_id, TraceBlobView message) {
148 current_generation_->InternMessage(field_id, std::move(message));
149 }
150
151 // Set the trace packet defaults for the current generation. If the current
152 // generation already has defaults set, starts a new generation without
153 // invalidating other incremental state (such as interned data).
UpdateTracePacketDefaults(TraceBlobView defaults)154 void UpdateTracePacketDefaults(TraceBlobView defaults) {
155 if (!current_generation_->GetTracePacketDefaultsView()) {
156 current_generation_->SetTracePacketDefaults(std::move(defaults));
157 return;
158 }
159
160 // The new defaults should only apply to subsequent messages on the
161 // sequence. Add a new generation with the updated defaults but the
162 // current generation's interned data state.
163 current_generation_.reset(new PacketSequenceStateGeneration(
164 this, generation_index_++, current_generation_->interned_data_,
165 std::move(defaults)));
166 }
167
SetThreadDescriptor(int32_t pid,int32_t tid,int64_t timestamp_ns,int64_t thread_timestamp_ns,int64_t thread_instruction_count)168 void SetThreadDescriptor(int32_t pid,
169 int32_t tid,
170 int64_t timestamp_ns,
171 int64_t thread_timestamp_ns,
172 int64_t thread_instruction_count) {
173 track_event_timestamps_valid_ = true;
174 pid_and_tid_valid_ = true;
175 pid_ = pid;
176 tid_ = tid;
177 track_event_timestamp_ns_ = timestamp_ns;
178 track_event_thread_timestamp_ns_ = thread_timestamp_ns;
179 track_event_thread_instruction_count_ = thread_instruction_count;
180 }
181
OnPacketLoss()182 void OnPacketLoss() {
183 packet_loss_ = true;
184 track_event_timestamps_valid_ = false;
185 }
186
187 // Starts a new generation with clean-slate incremental state and defaults.
OnIncrementalStateCleared()188 void OnIncrementalStateCleared() {
189 packet_loss_ = false;
190 current_generation_.reset(
191 new PacketSequenceStateGeneration(this, generation_index_++));
192 }
193
IsIncrementalStateValid()194 bool IsIncrementalStateValid() const { return !packet_loss_; }
195
sequence_stack_profile_tracker()196 SequenceStackProfileTracker& sequence_stack_profile_tracker() {
197 return sequence_stack_profile_tracker_;
198 }
199
200 // Returns a ref-counted ptr to the current generation.
current_generation()201 RefPtr<PacketSequenceStateGeneration> current_generation() const {
202 return current_generation_;
203 }
204
track_event_timestamps_valid()205 bool track_event_timestamps_valid() const {
206 return track_event_timestamps_valid_;
207 }
208
pid_and_tid_valid()209 bool pid_and_tid_valid() const { return pid_and_tid_valid_; }
210
pid()211 int32_t pid() const { return pid_; }
tid()212 int32_t tid() const { return tid_; }
213
context()214 TraceProcessorContext* context() const { return context_; }
215
216 private:
217 TraceProcessorContext* context_;
218
219 size_t generation_index_ = 0;
220
221 // If true, incremental state on the sequence is considered invalid until we
222 // see the next packet with incremental_state_cleared. We assume that we
223 // missed some packets at the beginning of the trace.
224 bool packet_loss_ = true;
225
226 // We can only consider TrackEvent delta timestamps to be correct after we
227 // have observed a thread descriptor (since the last packet loss).
228 bool track_event_timestamps_valid_ = false;
229
230 // |pid_| and |tid_| are only valid after we parsed at least one
231 // ThreadDescriptor packet on the sequence.
232 bool pid_and_tid_valid_ = false;
233
234 // Process/thread ID of the packet sequence set by a ThreadDescriptor
235 // packet. Used as default values for TrackEvents that don't specify a
236 // pid/tid override. Only valid after |pid_and_tid_valid_| is set to true.
237 int32_t pid_ = 0;
238 int32_t tid_ = 0;
239
240 // Current wall/thread timestamps/counters used as reference for the next
241 // TrackEvent delta timestamp.
242 int64_t track_event_timestamp_ns_ = 0;
243 int64_t track_event_thread_timestamp_ns_ = 0;
244 int64_t track_event_thread_instruction_count_ = 0;
245
246 RefPtr<PacketSequenceStateGeneration> current_generation_;
247 SequenceStackProfileTracker sequence_stack_profile_tracker_;
248 };
249
250 template <uint32_t FieldId, typename MessageType>
251 typename MessageType::Decoder*
LookupInternedMessage(uint64_t iid)252 PacketSequenceStateGeneration::LookupInternedMessage(uint64_t iid) {
253 auto* interned_message_view = GetInternedMessageView(FieldId, iid);
254 if (!interned_message_view)
255 return nullptr;
256
257 return interned_message_view->template GetOrCreateDecoder<MessageType>();
258 }
259
260 } // namespace trace_processor
261 } // namespace perfetto
262
263 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PACKET_SEQUENCE_STATE_H_
264