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