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 <optional>
20
21 #include "src/trace_processor/importers/common/args_tracker.h"
22 #include "src/trace_processor/importers/common/process_tracker.h"
23 #include "src/trace_processor/storage/trace_storage.h"
24
25 namespace perfetto {
26 namespace trace_processor {
27
28 namespace {
29
GetNameForGroup(TrackTracker::Group group)30 const char* GetNameForGroup(TrackTracker::Group group) {
31 switch (group) {
32 case TrackTracker::Group::kMemory:
33 return "Memory";
34 case TrackTracker::Group::kIo:
35 return "IO";
36 case TrackTracker::Group::kVirtio:
37 return "Virtio";
38 case TrackTracker::Group::kNetwork:
39 return "Network";
40 case TrackTracker::Group::kPower:
41 return "Power";
42 case TrackTracker::Group::kDeviceState:
43 return "Device State";
44 case TrackTracker::Group::kThermals:
45 return "Thermals";
46 case TrackTracker::Group::kClockFrequency:
47 return "Clock Freqeuncy";
48 case TrackTracker::Group::kSizeSentinel:
49 PERFETTO_FATAL("Unexpected size passed as group");
50 }
51 PERFETTO_FATAL("For GCC");
52 }
53
54 } // namespace
55
TrackTracker(TraceProcessorContext * context)56 TrackTracker::TrackTracker(TraceProcessorContext* context)
57 : source_key_(context->storage->InternString("source")),
58 source_id_key_(context->storage->InternString("source_id")),
59 source_id_is_process_scoped_key_(
60 context->storage->InternString("source_id_is_process_scoped")),
61 source_scope_key_(context->storage->InternString("source_scope")),
62 category_key_(context->storage->InternString("category")),
63 fuchsia_source_(context->storage->InternString("fuchsia")),
64 chrome_source_(context->storage->InternString("chrome")),
65 context_(context) {}
66
InternThreadTrack(UniqueTid utid)67 TrackId TrackTracker::InternThreadTrack(UniqueTid utid) {
68 auto it = thread_tracks_.find(utid);
69 if (it != thread_tracks_.end())
70 return it->second;
71
72 tables::ThreadTrackTable::Row row;
73 row.utid = utid;
74 auto id = context_->storage->mutable_thread_track_table()->Insert(row).id;
75 thread_tracks_[utid] = id;
76 return id;
77 }
78
InternProcessTrack(UniquePid upid)79 TrackId TrackTracker::InternProcessTrack(UniquePid upid) {
80 auto it = process_tracks_.find(upid);
81 if (it != process_tracks_.end())
82 return it->second;
83
84 tables::ProcessTrackTable::Row row;
85 row.upid = upid;
86 auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
87 process_tracks_[upid] = id;
88 return id;
89 }
90
InternFuchsiaAsyncTrack(StringId name,uint32_t upid,int64_t correlation_id)91 TrackId TrackTracker::InternFuchsiaAsyncTrack(StringId name,
92 uint32_t upid,
93 int64_t correlation_id) {
94 return InternLegacyChromeAsyncTrack(name, upid, correlation_id, false,
95 StringId());
96 }
97
InternCpuTrack(StringId name,uint32_t cpu)98 TrackId TrackTracker::InternCpuTrack(StringId name, uint32_t cpu) {
99 auto it = cpu_tracks_.find(std::make_pair(name, cpu));
100 if (it != cpu_tracks_.end()) {
101 return it->second;
102 }
103
104 tables::CpuTrackTable::Row row(name);
105 row.cpu = cpu;
106 auto id = context_->storage->mutable_cpu_track_table()->Insert(row).id;
107 cpu_tracks_[std::make_pair(name, cpu)] = id;
108
109 return id;
110 }
111
InternGpuTrack(const tables::GpuTrackTable::Row & row)112 TrackId TrackTracker::InternGpuTrack(const tables::GpuTrackTable::Row& row) {
113 GpuTrackTuple tuple{row.name, row.scope, row.context_id.value_or(0)};
114
115 auto it = gpu_tracks_.find(tuple);
116 if (it != gpu_tracks_.end())
117 return it->second;
118
119 auto id = context_->storage->mutable_gpu_track_table()->Insert(row).id;
120 gpu_tracks_[tuple] = id;
121 return id;
122 }
123
InternLegacyChromeAsyncTrack(StringId name,uint32_t upid,int64_t source_id,bool source_id_is_process_scoped,StringId source_scope)124 TrackId TrackTracker::InternLegacyChromeAsyncTrack(
125 StringId name,
126 uint32_t upid,
127 int64_t source_id,
128 bool source_id_is_process_scoped,
129 StringId source_scope) {
130 ChromeTrackTuple tuple;
131 if (source_id_is_process_scoped)
132 tuple.upid = upid;
133 tuple.source_id = source_id;
134 tuple.source_scope = source_scope;
135
136 auto it = chrome_tracks_.find(tuple);
137 if (it != chrome_tracks_.end()) {
138 if (name != kNullStringId) {
139 // The track may have been created for an end event without name. In that
140 // case, update it with this event's name.
141 auto* tracks = context_->storage->mutable_track_table();
142 uint32_t track_row = *tracks->id().IndexOf(it->second);
143 if (tracks->name()[track_row] == kNullStringId)
144 tracks->mutable_name()->Set(track_row, name);
145 }
146 return it->second;
147 }
148
149 // Legacy async tracks are always drawn in the context of a process, even if
150 // the ID's scope is global.
151 tables::ProcessTrackTable::Row track(name);
152 track.upid = upid;
153 TrackId id =
154 context_->storage->mutable_process_track_table()->Insert(track).id;
155 chrome_tracks_[tuple] = id;
156
157 context_->args_tracker->AddArgsTo(id)
158 .AddArg(source_key_, Variadic::String(chrome_source_))
159 .AddArg(source_id_key_, Variadic::Integer(source_id))
160 .AddArg(source_id_is_process_scoped_key_,
161 Variadic::Boolean(source_id_is_process_scoped))
162 .AddArg(source_scope_key_, Variadic::String(source_scope));
163
164 return id;
165 }
166
CreateGlobalAsyncTrack(StringId name,StringId source)167 TrackId TrackTracker::CreateGlobalAsyncTrack(StringId name, StringId source) {
168 tables::TrackTable::Row row(name);
169 auto id = context_->storage->mutable_track_table()->Insert(row).id;
170 if (!source.is_null()) {
171 context_->args_tracker->AddArgsTo(id).AddArg(source_key_,
172 Variadic::String(source));
173 }
174 return id;
175 }
176
CreateProcessAsyncTrack(StringId name,UniquePid upid,StringId source)177 TrackId TrackTracker::CreateProcessAsyncTrack(StringId name,
178 UniquePid upid,
179 StringId source) {
180 tables::ProcessTrackTable::Row row(name);
181 row.upid = upid;
182 auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
183 if (!source.is_null()) {
184 context_->args_tracker->AddArgsTo(id).AddArg(source_key_,
185 Variadic::String(source));
186 }
187 return id;
188 }
189
InternLegacyChromeProcessInstantTrack(UniquePid upid)190 TrackId TrackTracker::InternLegacyChromeProcessInstantTrack(UniquePid upid) {
191 auto it = chrome_process_instant_tracks_.find(upid);
192 if (it != chrome_process_instant_tracks_.end())
193 return it->second;
194
195 tables::ProcessTrackTable::Row row;
196 row.upid = upid;
197 auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
198 chrome_process_instant_tracks_[upid] = id;
199
200 context_->args_tracker->AddArgsTo(id).AddArg(
201 source_key_, Variadic::String(chrome_source_));
202
203 return id;
204 }
205
GetOrCreateLegacyChromeGlobalInstantTrack()206 TrackId TrackTracker::GetOrCreateLegacyChromeGlobalInstantTrack() {
207 if (!chrome_global_instant_track_id_) {
208 chrome_global_instant_track_id_ =
209 context_->storage->mutable_track_table()->Insert({}).id;
210
211 context_->args_tracker->AddArgsTo(*chrome_global_instant_track_id_)
212 .AddArg(source_key_, Variadic::String(chrome_source_));
213 }
214 return *chrome_global_instant_track_id_;
215 }
216
GetOrCreateTriggerTrack()217 TrackId TrackTracker::GetOrCreateTriggerTrack() {
218 if (trigger_track_id_) {
219 return *trigger_track_id_;
220 }
221 tables::TrackTable::Row row;
222 row.name = context_->storage->InternString("Trace Triggers");
223 trigger_track_id_ = context_->storage->mutable_track_table()->Insert(row).id;
224 return *trigger_track_id_;
225 }
226
InternGlobalCounterTrack(TrackTracker::Group group,StringId name,SetArgsCallback callback,StringId unit,StringId description)227 TrackId TrackTracker::InternGlobalCounterTrack(TrackTracker::Group group,
228 StringId name,
229 SetArgsCallback callback,
230 StringId unit,
231 StringId description) {
232 auto it = global_counter_tracks_by_name_.find(name);
233 if (it != global_counter_tracks_by_name_.end()) {
234 return it->second;
235 }
236
237 tables::CounterTrackTable::Row row(name);
238 row.parent_id = InternTrackForGroup(group);
239 row.unit = unit;
240 row.description = description;
241 TrackId track =
242 context_->storage->mutable_counter_track_table()->Insert(row).id;
243 global_counter_tracks_by_name_[name] = track;
244 if (callback) {
245 auto inserter = context_->args_tracker->AddArgsTo(track);
246 callback(inserter);
247 }
248 return track;
249 }
250
InternCpuCounterTrack(StringId name,uint32_t cpu)251 TrackId TrackTracker::InternCpuCounterTrack(StringId name, uint32_t cpu) {
252 auto it = cpu_counter_tracks_.find(std::make_pair(name, cpu));
253 if (it != cpu_counter_tracks_.end()) {
254 return it->second;
255 }
256
257 tables::CpuCounterTrackTable::Row row(name);
258 row.cpu = cpu;
259
260 TrackId track =
261 context_->storage->mutable_cpu_counter_track_table()->Insert(row).id;
262 cpu_counter_tracks_[std::make_pair(name, cpu)] = track;
263 return track;
264 }
265
InternThreadCounterTrack(StringId name,UniqueTid utid)266 TrackId TrackTracker::InternThreadCounterTrack(StringId name, UniqueTid utid) {
267 auto it = utid_counter_tracks_.find(std::make_pair(name, utid));
268 if (it != utid_counter_tracks_.end()) {
269 return it->second;
270 }
271
272 tables::ThreadCounterTrackTable::Row row(name);
273 row.utid = utid;
274
275 TrackId track =
276 context_->storage->mutable_thread_counter_track_table()->Insert(row).id;
277 utid_counter_tracks_[std::make_pair(name, utid)] = track;
278 return track;
279 }
280
InternProcessCounterTrack(StringId name,UniquePid upid,StringId unit,StringId description)281 TrackId TrackTracker::InternProcessCounterTrack(StringId name,
282 UniquePid upid,
283 StringId unit,
284 StringId description) {
285 auto it = upid_counter_tracks_.find(std::make_pair(name, upid));
286 if (it != upid_counter_tracks_.end()) {
287 return it->second;
288 }
289
290 tables::ProcessCounterTrackTable::Row row(name);
291 row.upid = upid;
292 row.unit = unit;
293 row.description = description;
294
295 TrackId track =
296 context_->storage->mutable_process_counter_track_table()->Insert(row).id;
297 upid_counter_tracks_[std::make_pair(name, upid)] = track;
298 return track;
299 }
300
InternIrqCounterTrack(StringId name,int32_t irq)301 TrackId TrackTracker::InternIrqCounterTrack(StringId name, int32_t irq) {
302 auto it = irq_counter_tracks_.find(std::make_pair(name, irq));
303 if (it != irq_counter_tracks_.end()) {
304 return it->second;
305 }
306
307 tables::IrqCounterTrackTable::Row row(name);
308 row.irq = irq;
309
310 TrackId track =
311 context_->storage->mutable_irq_counter_track_table()->Insert(row).id;
312 irq_counter_tracks_[std::make_pair(name, irq)] = track;
313 return track;
314 }
315
InternSoftirqCounterTrack(StringId name,int32_t softirq)316 TrackId TrackTracker::InternSoftirqCounterTrack(StringId name,
317 int32_t softirq) {
318 auto it = softirq_counter_tracks_.find(std::make_pair(name, softirq));
319 if (it != softirq_counter_tracks_.end()) {
320 return it->second;
321 }
322
323 tables::SoftirqCounterTrackTable::Row row(name);
324 row.softirq = softirq;
325
326 TrackId track =
327 context_->storage->mutable_softirq_counter_track_table()->Insert(row).id;
328 softirq_counter_tracks_[std::make_pair(name, softirq)] = track;
329 return track;
330 }
331
InternGpuCounterTrack(StringId name,uint32_t gpu_id)332 TrackId TrackTracker::InternGpuCounterTrack(StringId name, uint32_t gpu_id) {
333 auto it = gpu_counter_tracks_.find(std::make_pair(name, gpu_id));
334 if (it != gpu_counter_tracks_.end()) {
335 return it->second;
336 }
337 TrackId track = CreateGpuCounterTrack(name, gpu_id);
338 gpu_counter_tracks_[std::make_pair(name, gpu_id)] = track;
339 return track;
340 }
341
InternEnergyCounterTrack(StringId name,int32_t consumer_id,StringId consumer_type,int32_t ordinal)342 TrackId TrackTracker::InternEnergyCounterTrack(StringId name,
343 int32_t consumer_id,
344 StringId consumer_type,
345 int32_t ordinal) {
346 auto it = energy_counter_tracks_.find(std::make_pair(name, consumer_id));
347 if (it != energy_counter_tracks_.end()) {
348 return it->second;
349 }
350 tables::EnergyCounterTrackTable::Row row(name);
351 row.consumer_id = consumer_id;
352 row.consumer_type = consumer_type;
353 row.ordinal = ordinal;
354 TrackId track =
355 context_->storage->mutable_energy_counter_track_table()->Insert(row).id;
356 energy_counter_tracks_[std::make_pair(name, consumer_id)] = track;
357 return track;
358 }
359
InternUidCounterTrack(StringId name,int32_t uid)360 TrackId TrackTracker::InternUidCounterTrack(StringId name, int32_t uid) {
361 auto it = uid_counter_tracks_.find(std::make_pair(name, uid));
362 if (it != uid_counter_tracks_.end()) {
363 return it->second;
364 }
365
366 tables::UidCounterTrackTable::Row row(name);
367 row.uid = uid;
368 TrackId track =
369 context_->storage->mutable_uid_counter_track_table()->Insert(row).id;
370 uid_counter_tracks_[std::make_pair(name, uid)] = track;
371 return track;
372 }
373
InternEnergyPerUidCounterTrack(StringId name,int32_t consumer_id,int32_t uid)374 TrackId TrackTracker::InternEnergyPerUidCounterTrack(StringId name,
375 int32_t consumer_id,
376 int32_t uid) {
377 auto it = energy_per_uid_counter_tracks_.find(std::make_pair(name, uid));
378 if (it != energy_per_uid_counter_tracks_.end()) {
379 return it->second;
380 }
381
382 tables::EnergyPerUidCounterTrackTable::Row row(name);
383 row.consumer_id = consumer_id;
384 row.uid = uid;
385 TrackId track =
386 context_->storage->mutable_energy_per_uid_counter_track_table()
387 ->Insert(row)
388 .id;
389 energy_per_uid_counter_tracks_[std::make_pair(name, uid)] = track;
390 return track;
391 }
392
CreateGpuCounterTrack(StringId name,uint32_t gpu_id,StringId description,StringId unit)393 TrackId TrackTracker::CreateGpuCounterTrack(StringId name,
394 uint32_t gpu_id,
395 StringId description,
396 StringId unit) {
397 tables::GpuCounterTrackTable::Row row(name);
398 row.gpu_id = gpu_id;
399 row.description = description;
400 row.unit = unit;
401
402 return context_->storage->mutable_gpu_counter_track_table()->Insert(row).id;
403 }
404
CreatePerfCounterTrack(StringId name,uint32_t perf_session_id,uint32_t cpu,bool is_timebase)405 TrackId TrackTracker::CreatePerfCounterTrack(StringId name,
406 uint32_t perf_session_id,
407 uint32_t cpu,
408 bool is_timebase) {
409 tables::PerfCounterTrackTable::Row row(name);
410 row.perf_session_id = perf_session_id;
411 row.cpu = cpu;
412 row.is_timebase = is_timebase;
413 return context_->storage->mutable_perf_counter_track_table()->Insert(row).id;
414 }
415
InternTrackForGroup(TrackTracker::Group group)416 TrackId TrackTracker::InternTrackForGroup(TrackTracker::Group group) {
417 uint32_t group_idx = static_cast<uint32_t>(group);
418 const std::optional<TrackId>& group_id = group_track_ids_[group_idx];
419 if (group_id) {
420 return *group_id;
421 }
422
423 StringId id = context_->storage->InternString(GetNameForGroup(group));
424 TrackId track_id = context_->storage->mutable_track_table()->Insert({id}).id;
425 group_track_ids_[group_idx] = track_id;
426 return track_id;
427 }
428
429 } // namespace trace_processor
430 } // namespace perfetto
431