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