blob: d25e75acea42f584d9689adde4b67439edba2547 [file] [log] [blame]
Eric Seckler684a4f72019-04-26 14:34:07 +01001/*
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_PROTO_INCREMENTAL_STATE_H_
18#define SRC_TRACE_PROCESSOR_PROTO_INCREMENTAL_STATE_H_
19
20#include <stdint.h>
21
22#include <map>
23#include <unordered_map>
24
25#include "perfetto/protozero/proto_decoder.h"
26#include "src/trace_processor/trace_blob_view.h"
27
28#include "perfetto/trace/track_event/debug_annotation.pbzero.h"
29#include "perfetto/trace/track_event/task_execution.pbzero.h"
30#include "perfetto/trace/track_event/track_event.pbzero.h"
31
32namespace perfetto {
33namespace trace_processor {
34
35// Stores per-packet-sequence incremental state during trace parsing, such as
36// reference timestamps for delta timestamp calculation and interned messages.
37class ProtoIncrementalState {
38 public:
39 // Entry in an interning index, refers to the interned message.
40 template <typename MessageType>
41 struct InternedDataView {
42 typename MessageType::Decoder CreateDecoder() {
43 return typename MessageType::Decoder(message.data(), message.length());
44 }
45
46 TraceBlobView message;
47 };
48
49 template <typename MessageType>
50 using InternedDataMap =
51 std::unordered_map<uint32_t, InternedDataView<MessageType>>;
52
53 class PacketSequenceState {
54 public:
55 int64_t IncrementAndGetTrackEventTimeNs(int64_t delta_ns) {
56 PERFETTO_DCHECK(IsTrackEventStateValid());
57 track_event_timestamp_ns_ += delta_ns;
58 return track_event_timestamp_ns_;
59 }
60
61 int64_t IncrementAndGetTrackEventThreadTimeNs(int64_t delta_ns) {
62 PERFETTO_DCHECK(IsTrackEventStateValid());
63 track_event_thread_timestamp_ns_ += delta_ns;
64 return track_event_thread_timestamp_ns_;
65 }
66
67 void OnPacketLoss() {
68 packet_loss_ = true;
69 thread_descriptor_seen_ = false;
70 }
71
72 void OnIncrementalStateCleared() { packet_loss_ = false; }
73
74 void SetThreadDescriptor(int32_t pid,
75 int32_t tid,
76 int64_t timestamp_ns,
77 int64_t thread_timestamp_ns) {
78 thread_descriptor_seen_ = true;
79 pid_ = pid;
80 tid_ = tid;
81 track_event_timestamp_ns_ = timestamp_ns;
82 track_event_thread_timestamp_ns_ = thread_timestamp_ns;
83 }
84
85 bool IsIncrementalStateValid() const { return !packet_loss_; }
86
87 bool IsTrackEventStateValid() const {
88 return IsIncrementalStateValid() && thread_descriptor_seen_;
89 }
90
91 int32_t pid() const { return pid_; }
92 int32_t tid() const { return tid_; }
93
94 template <typename MessageType>
95 InternedDataMap<MessageType>* GetInternedDataMap();
96
97 private:
98 // If true, incremental state on the sequence is considered invalid until we
99 // see the next packet with incremental_state_cleared. We assume that we
100 // missed some packets at the beginning of the trace.
101 bool packet_loss_ = true;
102
103 // We can only consider TrackEvent delta timestamps to be correct after we
104 // have observed a thread descriptor (since the last packet loss).
105 bool thread_descriptor_seen_ = false;
106
107 // Process/thread ID of the packet sequence. Used as default values for
108 // TrackEvents that don't specify a pid/tid override. Only valid while
109 // |seen_thread_descriptor_| is true.
110 int32_t pid_ = 0;
111 int32_t tid_ = 0;
112
113 // Current wall/thread timestamps used as reference for the next TrackEvent
114 // delta timestamp.
115 int64_t track_event_timestamp_ns_ = 0;
116 int64_t track_event_thread_timestamp_ns_ = 0;
117
118 InternedDataMap<protos::pbzero::EventCategory> event_categories_;
119 InternedDataMap<protos::pbzero::LegacyEventName> legacy_event_names_;
120 InternedDataMap<protos::pbzero::DebugAnnotationName>
121 debug_annotation_names_;
122 InternedDataMap<protos::pbzero::SourceLocation> source_locations_;
123 };
124
125 // Returns the PacketSequenceState for the packet sequence with the given id.
126 // If this is a new sequence which we haven't tracked before, initializes and
127 // inserts a new PacketSequenceState into the state map.
128 PacketSequenceState* GetOrCreateStateForPacketSequence(uint32_t sequence_id) {
129 return &packet_sequence_states_[sequence_id];
130 }
131
132 private:
133 std::map<uint32_t, PacketSequenceState> packet_sequence_states_;
134};
135
136template <>
137inline ProtoIncrementalState::InternedDataMap<protos::pbzero::EventCategory>*
138ProtoIncrementalState::PacketSequenceState::GetInternedDataMap<
139 protos::pbzero::EventCategory>() {
140 return &event_categories_;
141}
142
143template <>
144inline ProtoIncrementalState::InternedDataMap<protos::pbzero::LegacyEventName>*
145ProtoIncrementalState::PacketSequenceState::GetInternedDataMap<
146 protos::pbzero::LegacyEventName>() {
147 return &legacy_event_names_;
148}
149
150template <>
151inline ProtoIncrementalState::InternedDataMap<
152 protos::pbzero::DebugAnnotationName>*
153ProtoIncrementalState::PacketSequenceState::GetInternedDataMap<
154 protos::pbzero::DebugAnnotationName>() {
155 return &debug_annotation_names_;
156}
157
158template <>
159inline ProtoIncrementalState::InternedDataMap<protos::pbzero::SourceLocation>*
160ProtoIncrementalState::PacketSequenceState::GetInternedDataMap<
161 protos::pbzero::SourceLocation>() {
162 return &source_locations_;
163}
164
165} // namespace trace_processor
166} // namespace perfetto
167
168#endif // SRC_TRACE_PROCESSOR_PROTO_INCREMENTAL_STATE_H_