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