1 /*
2 * Copyright (C) 2019 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 #include "src/trace_processor/importers/common/track_tracker.h"
18
19 #include "src/trace_processor/importers/common/args_tracker.h"
20 #include "src/trace_processor/importers/common/process_tracker.h"
21
22 namespace perfetto {
23 namespace trace_processor {
24
TrackTracker(TraceProcessorContext * context)25 TrackTracker::TrackTracker(TraceProcessorContext* context)
26 : source_key_(context->storage->InternString("source")),
27 source_id_key_(context->storage->InternString("source_id")),
28 source_id_is_process_scoped_key_(
29 context->storage->InternString("source_id_is_process_scoped")),
30 source_scope_key_(context->storage->InternString("source_scope")),
31 category_key_(context->storage->InternString("category")),
32 fuchsia_source_(context->storage->InternString("fuchsia")),
33 chrome_source_(context->storage->InternString("chrome")),
34 android_source_(context->storage->InternString("android")),
35 context_(context) {}
36
InternThreadTrack(UniqueTid utid)37 TrackId TrackTracker::InternThreadTrack(UniqueTid utid) {
38 auto it = thread_tracks_.find(utid);
39 if (it != thread_tracks_.end())
40 return it->second;
41
42 tables::ThreadTrackTable::Row row;
43 row.utid = utid;
44 auto id = context_->storage->mutable_thread_track_table()->Insert(row).id;
45 thread_tracks_[utid] = id;
46 return id;
47 }
48
InternProcessTrack(UniquePid upid)49 TrackId TrackTracker::InternProcessTrack(UniquePid upid) {
50 auto it = process_tracks_.find(upid);
51 if (it != process_tracks_.end())
52 return it->second;
53
54 tables::ProcessTrackTable::Row row;
55 row.upid = upid;
56 auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
57 process_tracks_[upid] = id;
58 return id;
59 }
60
InternFuchsiaAsyncTrack(StringId name,uint32_t upid,int64_t correlation_id)61 TrackId TrackTracker::InternFuchsiaAsyncTrack(StringId name,
62 uint32_t upid,
63 int64_t correlation_id) {
64 return InternLegacyChromeAsyncTrack(name, upid, correlation_id, false,
65 StringId());
66 }
67
InternCpuTrack(StringId name,uint32_t cpu)68 TrackId TrackTracker::InternCpuTrack(StringId name, uint32_t cpu) {
69 auto it = cpu_tracks_.find(std::make_pair(name, cpu));
70 if (it != cpu_tracks_.end()) {
71 return it->second;
72 }
73
74 tables::TrackTable::Row row(name);
75 auto id = context_->storage->mutable_track_table()->Insert(row).id;
76 cpu_tracks_[std::make_pair(name, cpu)] = id;
77
78 return id;
79 }
80
InternGpuTrack(const tables::GpuTrackTable::Row & row)81 TrackId TrackTracker::InternGpuTrack(const tables::GpuTrackTable::Row& row) {
82 GpuTrackTuple tuple{row.name, row.scope, row.context_id.value_or(0)};
83
84 auto it = gpu_tracks_.find(tuple);
85 if (it != gpu_tracks_.end())
86 return it->second;
87
88 auto id = context_->storage->mutable_gpu_track_table()->Insert(row).id;
89 gpu_tracks_[tuple] = id;
90 return id;
91 }
92
InternLegacyChromeAsyncTrack(StringId name,uint32_t upid,int64_t source_id,bool source_id_is_process_scoped,StringId source_scope)93 TrackId TrackTracker::InternLegacyChromeAsyncTrack(
94 StringId name,
95 uint32_t upid,
96 int64_t source_id,
97 bool source_id_is_process_scoped,
98 StringId source_scope) {
99 ChromeTrackTuple tuple;
100 if (source_id_is_process_scoped)
101 tuple.upid = upid;
102 tuple.source_id = source_id;
103 tuple.source_scope = source_scope;
104
105 auto it = chrome_tracks_.find(tuple);
106 if (it != chrome_tracks_.end()) {
107 if (name != kNullStringId) {
108 // The track may have been created for an end event without name. In that
109 // case, update it with this event's name.
110 auto* tracks = context_->storage->mutable_track_table();
111 uint32_t track_row = *tracks->id().IndexOf(it->second);
112 if (tracks->name()[track_row] == kNullStringId)
113 tracks->mutable_name()->Set(track_row, name);
114 }
115 return it->second;
116 }
117
118 // Legacy async tracks are always drawn in the context of a process, even if
119 // the ID's scope is global.
120 tables::ProcessTrackTable::Row track(name);
121 track.upid = upid;
122 TrackId id =
123 context_->storage->mutable_process_track_table()->Insert(track).id;
124 chrome_tracks_[tuple] = id;
125
126 context_->args_tracker->AddArgsTo(id)
127 .AddArg(source_key_, Variadic::String(chrome_source_))
128 .AddArg(source_id_key_, Variadic::Integer(source_id))
129 .AddArg(source_id_is_process_scoped_key_,
130 Variadic::Boolean(source_id_is_process_scoped))
131 .AddArg(source_scope_key_, Variadic::String(source_scope));
132
133 return id;
134 }
135
CreateGlobalAsyncTrack(StringId name)136 TrackId TrackTracker::CreateGlobalAsyncTrack(StringId name) {
137 tables::TrackTable::Row row(name);
138 auto id = context_->storage->mutable_track_table()->Insert(row).id;
139 return id;
140 }
141
CreateAndroidAsyncTrack(StringId name,UniquePid upid)142 TrackId TrackTracker::CreateAndroidAsyncTrack(StringId name, UniquePid upid) {
143 tables::ProcessTrackTable::Row row(name);
144 row.upid = upid;
145 auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
146 context_->args_tracker->AddArgsTo(id).AddArg(
147 source_key_, Variadic::String(android_source_));
148 return id;
149 }
150
CreateFrameTimelineAsyncTrack(StringId name,UniquePid upid)151 TrackId TrackTracker::CreateFrameTimelineAsyncTrack(StringId name,
152 UniquePid upid) {
153 tables::ProcessTrackTable::Row row(name);
154 row.upid = upid;
155 return context_->storage->mutable_process_track_table()->Insert(row).id;
156 }
157
InternLegacyChromeProcessInstantTrack(UniquePid upid)158 TrackId TrackTracker::InternLegacyChromeProcessInstantTrack(UniquePid upid) {
159 auto it = chrome_process_instant_tracks_.find(upid);
160 if (it != chrome_process_instant_tracks_.end())
161 return it->second;
162
163 tables::ProcessTrackTable::Row row;
164 row.upid = upid;
165 auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
166 chrome_process_instant_tracks_[upid] = id;
167
168 context_->args_tracker->AddArgsTo(id).AddArg(
169 source_key_, Variadic::String(chrome_source_));
170
171 return id;
172 }
173
GetOrCreateLegacyChromeGlobalInstantTrack()174 TrackId TrackTracker::GetOrCreateLegacyChromeGlobalInstantTrack() {
175 if (!chrome_global_instant_track_id_) {
176 chrome_global_instant_track_id_ =
177 context_->storage->mutable_track_table()->Insert({}).id;
178
179 context_->args_tracker->AddArgsTo(*chrome_global_instant_track_id_)
180 .AddArg(source_key_, Variadic::String(chrome_source_));
181 }
182 return *chrome_global_instant_track_id_;
183 }
184
GetOrCreateTriggerTrack()185 TrackId TrackTracker::GetOrCreateTriggerTrack() {
186 if (trigger_track_id_) {
187 return *trigger_track_id_;
188 }
189 tables::TrackTable::Row row;
190 row.name = context_->storage->InternString("Trace Triggers");
191 trigger_track_id_ = context_->storage->mutable_track_table()->Insert(row).id;
192 return *trigger_track_id_;
193 }
194
InternGlobalCounterTrack(StringId name,StringId unit,StringId description)195 TrackId TrackTracker::InternGlobalCounterTrack(StringId name,
196 StringId unit,
197 StringId description) {
198 auto it = global_counter_tracks_by_name_.find(name);
199 if (it != global_counter_tracks_by_name_.end()) {
200 return it->second;
201 }
202
203 tables::CounterTrackTable::Row row(name);
204 row.unit = unit;
205 row.description = description;
206 TrackId track =
207 context_->storage->mutable_counter_track_table()->Insert(row).id;
208 global_counter_tracks_by_name_[name] = track;
209 return track;
210 }
211
InternCpuCounterTrack(StringId name,uint32_t cpu)212 TrackId TrackTracker::InternCpuCounterTrack(StringId name, uint32_t cpu) {
213 auto it = cpu_counter_tracks_.find(std::make_pair(name, cpu));
214 if (it != cpu_counter_tracks_.end()) {
215 return it->second;
216 }
217
218 tables::CpuCounterTrackTable::Row row(name);
219 row.cpu = cpu;
220
221 TrackId track =
222 context_->storage->mutable_cpu_counter_track_table()->Insert(row).id;
223 cpu_counter_tracks_[std::make_pair(name, cpu)] = track;
224 return track;
225 }
226
InternThreadCounterTrack(StringId name,UniqueTid utid)227 TrackId TrackTracker::InternThreadCounterTrack(StringId name, UniqueTid utid) {
228 auto it = utid_counter_tracks_.find(std::make_pair(name, utid));
229 if (it != utid_counter_tracks_.end()) {
230 return it->second;
231 }
232
233 tables::ThreadCounterTrackTable::Row row(name);
234 row.utid = utid;
235
236 TrackId track =
237 context_->storage->mutable_thread_counter_track_table()->Insert(row).id;
238 utid_counter_tracks_[std::make_pair(name, utid)] = track;
239 return track;
240 }
241
InternProcessCounterTrack(StringId name,UniquePid upid,StringId unit,StringId description)242 TrackId TrackTracker::InternProcessCounterTrack(StringId name,
243 UniquePid upid,
244 StringId unit,
245 StringId description) {
246 auto it = upid_counter_tracks_.find(std::make_pair(name, upid));
247 if (it != upid_counter_tracks_.end()) {
248 return it->second;
249 }
250
251 tables::ProcessCounterTrackTable::Row row(name);
252 row.upid = upid;
253 row.unit = unit;
254 row.description = description;
255
256 TrackId track =
257 context_->storage->mutable_process_counter_track_table()->Insert(row).id;
258 upid_counter_tracks_[std::make_pair(name, upid)] = track;
259 return track;
260 }
261
InternIrqCounterTrack(StringId name,int32_t irq)262 TrackId TrackTracker::InternIrqCounterTrack(StringId name, int32_t irq) {
263 auto it = irq_counter_tracks_.find(std::make_pair(name, irq));
264 if (it != irq_counter_tracks_.end()) {
265 return it->second;
266 }
267
268 tables::IrqCounterTrackTable::Row row(name);
269 row.irq = irq;
270
271 TrackId track =
272 context_->storage->mutable_irq_counter_track_table()->Insert(row).id;
273 irq_counter_tracks_[std::make_pair(name, irq)] = track;
274 return track;
275 }
276
InternSoftirqCounterTrack(StringId name,int32_t softirq)277 TrackId TrackTracker::InternSoftirqCounterTrack(StringId name,
278 int32_t softirq) {
279 auto it = softirq_counter_tracks_.find(std::make_pair(name, softirq));
280 if (it != softirq_counter_tracks_.end()) {
281 return it->second;
282 }
283
284 tables::SoftirqCounterTrackTable::Row row(name);
285 row.softirq = softirq;
286
287 TrackId track =
288 context_->storage->mutable_softirq_counter_track_table()->Insert(row).id;
289 softirq_counter_tracks_[std::make_pair(name, softirq)] = track;
290 return track;
291 }
292
InternGpuCounterTrack(StringId name,uint32_t gpu_id)293 TrackId TrackTracker::InternGpuCounterTrack(StringId name, uint32_t gpu_id) {
294 auto it = gpu_counter_tracks_.find(std::make_pair(name, gpu_id));
295 if (it != gpu_counter_tracks_.end()) {
296 return it->second;
297 }
298 TrackId track = CreateGpuCounterTrack(name, gpu_id);
299 gpu_counter_tracks_[std::make_pair(name, gpu_id)] = track;
300 return track;
301 }
302
CreateGpuCounterTrack(StringId name,uint32_t gpu_id,StringId description,StringId unit)303 TrackId TrackTracker::CreateGpuCounterTrack(StringId name,
304 uint32_t gpu_id,
305 StringId description,
306 StringId unit) {
307 tables::GpuCounterTrackTable::Row row(name);
308 row.gpu_id = gpu_id;
309 row.description = description;
310 row.unit = unit;
311
312 return context_->storage->mutable_gpu_counter_track_table()->Insert(row).id;
313 }
314
CreatePerfCounterTrack(StringId name,uint32_t perf_session_id,uint32_t cpu,bool is_timebase)315 TrackId TrackTracker::CreatePerfCounterTrack(StringId name,
316 uint32_t perf_session_id,
317 uint32_t cpu,
318 bool is_timebase) {
319 tables::PerfCounterTrackTable::Row row(name);
320 row.perf_session_id = perf_session_id;
321 row.cpu = cpu;
322 row.is_timebase = is_timebase;
323 return context_->storage->mutable_perf_counter_track_table()->Insert(row).id;
324 }
325
326 } // namespace trace_processor
327 } // namespace perfetto
328