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