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