• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 <vector>
19 
20 #include <inttypes.h>
21 
22 #include "perfetto/ext/base/optional.h"
23 #include "src/trace_processor/importers/common/process_tracker.h"
24 #include "src/trace_processor/importers/common/slice_tracker.h"
25 #include "src/trace_processor/importers/common/track_tracker.h"
26 #include "src/trace_processor/storage/trace_storage.h"
27 #include "src/trace_processor/types/trace_processor_context.h"
28 
29 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
30 #include <cxxabi.h>
31 #endif
32 
33 namespace perfetto {
34 namespace trace_processor {
35 namespace {
36 // TODO(rsavitski): consider using the sampling rate from the trace config.
37 constexpr int64_t kFixedStackSliceDurationNs = 1 * 1000 * 1000;
38 }  // namespace
39 
AddStackToSliceTrack(int64_t timestamp,CallsiteId leaf_id,uint32_t pid,uint32_t tid,uint32_t cpu)40 void PerfSampleTracker::AddStackToSliceTrack(int64_t timestamp,
41                                              CallsiteId leaf_id,
42                                              uint32_t pid,
43                                              uint32_t tid,
44                                              uint32_t cpu) {
45   UniquePid upid =
46       context_->process_tracker->GetOrCreateProcess(static_cast<uint32_t>(pid));
47 
48   TrackId track_id = context_->track_tracker->InternPerfStackTrack(upid);
49   const auto& callsites = context_->storage->stack_profile_callsite_table();
50   const auto& frames = context_->storage->stack_profile_frame_table();
51   const auto& mappings = context_->storage->stack_profile_mapping_table();
52 
53   // Synthetic frame for more context, as the track is process-wide.
54   char buf[128] = {};
55   snprintf(buf, sizeof(buf), "cpu: [%" PRIu32 "]; thread: [%" PRIi32 "]", cpu,
56            tid);
57   StringId synth = context_->storage->InternString(buf);
58   context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId, synth,
59                                   kFixedStackSliceDurationNs);
60 
61   // The callstack id references the leaf frame, while we want the slice stack
62   // to have the root frame at the top in the UI, so walk the chain in reverse.
63   std::vector<uint32_t> callsite_rows;
64   callsite_rows.reserve(64);
65   base::Optional<CallsiteId> cs_id = leaf_id;
66   while (cs_id) {
67     uint32_t row = *callsites.id().IndexOf(*cs_id);
68     callsite_rows.push_back(row);
69     cs_id = callsites.parent_id()[row];
70   }
71 
72   for (auto rit = callsite_rows.rbegin(); rit != callsite_rows.rend(); ++rit) {
73     uint32_t callsite_row = *rit;
74     FrameId frame_id = callsites.frame_id()[callsite_row];
75     uint32_t frame_row = *frames.id().IndexOf(frame_id);
76 
77     MappingId mapping_id = frames.mapping()[frame_row];
78     uint32_t mapping_row = *mappings.id().IndexOf(mapping_id);
79 
80     StringId mangled_fname = frames.name()[frame_row];
81     StringId mname = mappings.name()[mapping_row];
82 
83     StringId fname = MaybeDemangle(mangled_fname);
84     context_->slice_tracker->Scoped(timestamp, track_id, mname, fname,
85                                     kFixedStackSliceDurationNs);
86   }
87 }
88 
89 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
MaybeDemangle(StringId fname)90 StringId PerfSampleTracker::MaybeDemangle(StringId fname) {
91   StringId ret = fname;
92   const char* raw_fname = context_->storage->GetString(fname).c_str();
93   int ignored;
94   char* data = abi::__cxa_demangle(raw_fname, nullptr, nullptr, &ignored);
95   if (data) {
96     ret = context_->storage->InternString(data);
97     free(data);
98   }
99   return ret;
100 }
101 #else
MaybeDemangle(StringId fname)102 StringId PerfSampleTracker::MaybeDemangle(StringId fname) {
103   return fname;
104 }
105 #endif
106 
107 }  // namespace trace_processor
108 }  // namespace perfetto
109