xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/common/slice_tracker.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2018 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_COMMON_SLICE_TRACKER_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SLICE_TRACKER_H_
19 
20 #include <stdint.h>
21 
22 #include "perfetto/ext/base/flat_hash_map.h"
23 #include "src/trace_processor/importers/common/args_tracker.h"
24 #include "src/trace_processor/importers/common/slice_translation_table.h"
25 #include "src/trace_processor/storage/trace_storage.h"
26 
27 namespace perfetto {
28 namespace trace_processor {
29 
30 class ArgsTracker;
31 class TraceProcessorContext;
32 
33 class SliceTracker {
34  public:
35   using SetArgsCallback = std::function<void(ArgsTracker::BoundInserter*)>;
36   using OnSliceBeginCallback = std::function<void(TrackId, SliceId)>;
37 
38   explicit SliceTracker(TraceProcessorContext*);
39   virtual ~SliceTracker();
40 
41   // virtual for testing
42   virtual std::optional<SliceId> Begin(
43       int64_t timestamp,
44       TrackId track_id,
45       StringId category,
46       StringId raw_name,
47       SetArgsCallback args_callback = SetArgsCallback());
48 
49   // Unnestable slices are slices which do not have any concept of nesting so
50   // starting a new slice when a slice already exists leads to no new slice
51   // being added. The number of times a begin event is seen is tracked as well
52   // as the latest time we saw a begin event. For legacy Android use only. See
53   // the comment in SystraceParser::ParseSystracePoint for information on why
54   // this method exists.
55   void BeginLegacyUnnestable(tables::SliceTable::Row row,
56                              SetArgsCallback args_callback);
57 
58   template <typename Table>
59   std::optional<SliceId> BeginTyped(
60       Table* table,
61       typename Table::Row row,
62       SetArgsCallback args_callback = SetArgsCallback()) {
63     // Ensure that the duration is pending for this row.
64     row.dur = kPendingDuration;
65     if (row.name) {
66       row.name = context_->slice_translation_table->TranslateName(*row.name);
67     }
68     return StartSlice(row.ts, row.track_id, args_callback,
69                       [table, &row]() { return table->Insert(row).id; });
70   }
71 
72   // virtual for testing
73   virtual std::optional<SliceId> Scoped(
74       int64_t timestamp,
75       TrackId track_id,
76       StringId category,
77       StringId raw_name,
78       int64_t duration,
79       SetArgsCallback args_callback = SetArgsCallback());
80 
81   template <typename Table>
82   std::optional<SliceId> ScopedTyped(
83       Table* table,
84       typename Table::Row row,
85       SetArgsCallback args_callback = SetArgsCallback()) {
86     PERFETTO_DCHECK(row.dur >= 0);
87     if (row.name) {
88       row.name = context_->slice_translation_table->TranslateName(*row.name);
89     }
90     return StartSlice(row.ts, row.track_id, args_callback,
91                       [table, &row]() { return table->Insert(row).id; });
92   }
93 
94   // virtual for testing
95   virtual std::optional<SliceId> End(
96       int64_t timestamp,
97       TrackId track_id,
98       StringId opt_category = {},
99       StringId opt_raw_name = {},
100       SetArgsCallback args_callback = SetArgsCallback());
101 
102   // Usually args should be added in the Begin or End args_callback but this
103   // method is for the situation where new args need to be added to an
104   // in-progress slice.
105   std::optional<uint32_t> AddArgs(TrackId track_id,
106                                   StringId category,
107                                   StringId name,
108                                   SetArgsCallback args_callback);
109 
110   void FlushPendingSlices();
111 
112   void SetOnSliceBeginCallback(OnSliceBeginCallback callback);
113 
114   std::optional<SliceId> GetTopmostSliceOnTrack(TrackId track_id) const;
115 
116  private:
117   // Slices which have been opened but haven't been closed yet will be marked
118   // with this duration placeholder.
119   static constexpr int64_t kPendingDuration = -1;
120 
121   struct SliceInfo {
122     tables::SliceTable::RowNumber row;
123     ArgsTracker args_tracker;
124   };
125   using SlicesStack = std::vector<SliceInfo>;
126 
127   struct TrackInfo {
128     SlicesStack slice_stack;
129 
130     // These field is only valid for legacy unnestable slices.
131     bool is_legacy_unnestable = false;
132     uint32_t legacy_unnestable_begin_count = 0;
133     int64_t legacy_unnestable_last_begin_ts = 0;
134   };
135   using StackMap = base::FlatHashMap<TrackId, TrackInfo>;
136 
137   // Args pending translation.
138   struct TranslatableArgs {
139     SliceId slice_id;
140     ArgsTracker::CompactArgSet compact_arg_set;
141   };
142 
143   // virtual for testing.
144   virtual std::optional<SliceId> StartSlice(int64_t timestamp,
145                                             TrackId track_id,
146                                             SetArgsCallback args_callback,
147                                             std::function<SliceId()> inserter);
148 
149   std::optional<SliceId> CompleteSlice(
150       int64_t timestamp,
151       TrackId track_id,
152       SetArgsCallback args_callback,
153       std::function<std::optional<uint32_t>(const SlicesStack&)> finder);
154 
155   void MaybeCloseStack(int64_t end_ts, const SlicesStack&, TrackId track_id);
156 
157   std::optional<uint32_t> MatchingIncompleteSliceIndex(const SlicesStack& stack,
158                                                        StringId name,
159                                                        StringId category);
160 
161   int64_t GetStackHash(const SlicesStack&);
162 
163   void StackPop(TrackId track_id);
164   void StackPush(TrackId track_id, tables::SliceTable::RowReference);
165   void FlowTrackerUpdate(TrackId track_id);
166 
167   // If args need translation, adds them to a list of pending translatable args,
168   // so that they are translated at the end of the trace. Takes ownership of the
169   // arg set for the slice. Otherwise, this is a noop, and the args are added to
170   // the args table immediately when the slice is popped.
171   void MaybeAddTranslatableArgs(SliceInfo& slice_info);
172 
173   OnSliceBeginCallback on_slice_begin_callback_;
174 
175   // Timestamp of the previous event. Used to discard events arriving out
176   // of order.
177   int64_t prev_timestamp_ = std::numeric_limits<int64_t>::min();
178 
179   const StringId legacy_unnestable_begin_count_string_id_;
180   const StringId legacy_unnestable_last_begin_ts_string_id_;
181 
182   TraceProcessorContext* const context_;
183   StackMap stacks_;
184   std::vector<TranslatableArgs> translatable_args_;
185 };
186 
187 }  // namespace trace_processor
188 }  // namespace perfetto
189 
190 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SLICE_TRACKER_H_
191