• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "src/trace_processor/importers/proto/perf_sample_tracker.h"
17 
18 #include <inttypes.h>
19 #include <stdio.h>
20 
21 #include "src/trace_processor/importers/common/track_tracker.h"
22 #include "src/trace_processor/storage/trace_storage.h"
23 #include "src/trace_processor/types/trace_processor_context.h"
24 
25 #include "protos/perfetto/common/perf_events.pbzero.h"
26 #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
27 #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
28 
29 namespace perfetto {
30 namespace trace_processor {
31 
32 namespace {
33 // Follow perf tool naming convention.
StringifyCounter(int32_t counter)34 const char* StringifyCounter(int32_t counter) {
35   using protos::pbzero::PerfEvents;
36   switch (counter) {
37     case (PerfEvents::SW_CPU_CLOCK):
38       return "cpu-clock";
39     case (PerfEvents::SW_PAGE_FAULTS):
40       return "page-faults";
41     case (PerfEvents::HW_CPU_CYCLES):
42       return "cpu-cycles";
43     case (PerfEvents::HW_INSTRUCTIONS):
44       return "instructions";
45     default:
46       break;
47   }
48   return "unknown";
49 }
50 
InternTimebaseCounterName(protos::pbzero::TracePacketDefaults::Decoder * defaults,TraceProcessorContext * context)51 StringId InternTimebaseCounterName(
52     protos::pbzero::TracePacketDefaults::Decoder* defaults,
53     TraceProcessorContext* context) {
54   using namespace protos::pbzero;
55   PerfSampleDefaults::Decoder perf_defaults(defaults->perf_sample_defaults());
56   PerfEvents::Timebase::Decoder timebase(perf_defaults.timebase());
57 
58   if (timebase.counter() != PerfEvents::UNKNOWN_COUNTER) {
59     return context->storage->InternString(StringifyCounter(timebase.counter()));
60   }
61   PerfEvents::Tracepoint::Decoder tracepoint(timebase.tracepoint());
62   return context->storage->InternString(tracepoint.name());
63 }
64 }  // namespace
65 
GetSamplingStreamInfo(uint32_t seq_id,uint32_t cpu,protos::pbzero::TracePacketDefaults::Decoder * nullable_defaults)66 PerfSampleTracker::SamplingStreamInfo PerfSampleTracker::GetSamplingStreamInfo(
67     uint32_t seq_id,
68     uint32_t cpu,
69     protos::pbzero::TracePacketDefaults::Decoder* nullable_defaults) {
70   auto seq_it = seq_state_.find(seq_id);
71   if (seq_it == seq_state_.end()) {
72     seq_it = seq_state_.emplace(seq_id, next_perf_session_id_++).first;
73   }
74   SequenceState* seq_state = &seq_it->second;
75   uint32_t session_id = seq_state->perf_session_id;
76 
77   auto cpu_it = seq_state->per_cpu.find(cpu);
78   if (cpu_it != seq_state->per_cpu.end())
79     return {seq_state->perf_session_id, cpu_it->second.timebase_track_id};
80 
81   // No defaults means legacy producer implementation, assume default timebase
82   // of per-cpu timer. Always the case for Android R builds, and it isn't worth
83   // guaranteeing support for intermediate S builds in this aspect.
84   StringId name_id = kNullStringId;
85   if (!nullable_defaults || !nullable_defaults->has_perf_sample_defaults()) {
86     name_id = context_->storage->InternString(
87         StringifyCounter(protos::pbzero::PerfEvents::SW_CPU_CLOCK));
88   } else {
89     name_id = InternTimebaseCounterName(nullable_defaults, context_);
90   }
91 
92   TrackId timebase_track_id = context_->track_tracker->CreatePerfCounterTrack(
93       name_id, session_id, cpu, /*is_timebase=*/true);
94 
95   seq_state->per_cpu.emplace(cpu, timebase_track_id);
96 
97   return {session_id, timebase_track_id};
98 }
99 
100 }  // namespace trace_processor
101 }  // namespace perfetto
102