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