• 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 
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