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 base::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 base::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 base::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 base::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 base::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 base::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 base::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 uint32_t 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 // virtual for testing. 138 virtual base::Optional<SliceId> StartSlice(int64_t timestamp, 139 TrackId track_id, 140 SetArgsCallback args_callback, 141 std::function<SliceId()> inserter); 142 143 base::Optional<SliceId> CompleteSlice( 144 int64_t timestamp, 145 TrackId track_id, 146 SetArgsCallback args_callback, 147 std::function<base::Optional<uint32_t>(const SlicesStack&)> finder); 148 149 void MaybeCloseStack(int64_t end_ts, SlicesStack*, TrackId track_id); 150 151 base::Optional<uint32_t> MatchingIncompleteSliceIndex( 152 const SlicesStack& stack, 153 StringId name, 154 StringId category); 155 156 int64_t GetStackHash(const SlicesStack&); 157 158 void StackPop(TrackId track_id); 159 void StackPush(TrackId track_id, uint32_t slice_idx); 160 void FlowTrackerUpdate(TrackId track_id); 161 162 OnSliceBeginCallback on_slice_begin_callback_; 163 164 // Timestamp of the previous event. Used to discard events arriving out 165 // of order. 166 int64_t prev_timestamp_ = std::numeric_limits<int64_t>::min(); 167 168 const StringId legacy_unnestable_begin_count_string_id_; 169 const StringId legacy_unnestable_last_begin_ts_string_id_; 170 171 TraceProcessorContext* const context_; 172 StackMap stacks_; 173 }; 174 175 } // namespace trace_processor 176 } // namespace perfetto 177 178 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SLICE_TRACKER_H_ 179