• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "trace_dumper.h"
17 
18 namespace ark::tooling::sampler {
19 
DumpTraces(const SampleInfo & sample,size_t count)20 void TraceDumper::DumpTraces(const SampleInfo &sample, size_t count)
21 {
22     std::ofstream &stream = ResolveStream(sample);
23 
24     for (size_t i = sample.stackInfo.managedStackSize; i-- > 0;) {
25         uintptr_t pfId = sample.stackInfo.managedStack[i].pandaFilePtr;
26         uint64_t fileId = sample.stackInfo.managedStack[i].fileId;
27 
28         std::string fullMethodName;
29         if (pfId == helpers::ToUnderlying(FrameKind::BRIDGE)) {
30             if (!buildSystemFrames_) {
31                 continue;
32             }
33 
34             fullMethodName = "System_Frame";
35         } else {
36             const panda_file::File *pf = nullptr;
37             auto it = modulesMap_->find(pfId);
38             if (it != modulesMap_->end()) {
39                 pf = it->second.get();
40             }
41 
42             fullMethodName = ResolveName(pf, fileId);
43         }
44         stream << fullMethodName << "; ";
45     }
46     stream << count << "\n";
47 }
48 
SetBuildSystemFrames(bool buildSystemFrames)49 void TraceDumper::SetBuildSystemFrames(bool buildSystemFrames)
50 {
51     buildSystemFrames_ = buildSystemFrames;
52 }
53 
54 /* static */
WriteThreadId(std::ofstream & stream,uint32_t threadId)55 void TraceDumper::WriteThreadId(std::ofstream &stream, uint32_t threadId)
56 {
57     stream << "thread_id = " << threadId << "; ";
58 }
59 
60 /* static */
WriteThreadStatus(std::ofstream & stream,SampleInfo::ThreadStatus threadStatus)61 void TraceDumper::WriteThreadStatus(std::ofstream &stream, SampleInfo::ThreadStatus threadStatus)
62 {
63     stream << "status = ";
64 
65     switch (threadStatus) {
66         case SampleInfo::ThreadStatus::RUNNING: {
67             stream << "active; ";
68             break;
69         }
70         case SampleInfo::ThreadStatus::SUSPENDED: {
71             stream << "suspended; ";
72             break;
73         }
74         default: {
75             UNREACHABLE();
76         }
77     }
78 }
79 
ResolveName(const panda_file::File * pf,uint64_t fileId) const80 std::string TraceDumper::ResolveName(const panda_file::File *pf, uint64_t fileId) const
81 {
82     if (pf == nullptr) {
83         return std::string("__unknown_module::" + std::to_string(fileId));
84     }
85 
86     auto it = methodsMap_->find(pf);
87     if (it != methodsMap_->end()) {
88         return it->second.at(fileId);
89     }
90 
91     return pf->GetFilename() + "::__unknown_" + std::to_string(fileId);
92 }
93 
94 /* override */
ResolveStream(const SampleInfo & sample)95 std::ofstream &SingleCSVDumper::ResolveStream(const SampleInfo &sample)
96 {
97     if (option_ == DumpType::THREAD_SEPARATION_BY_TID) {
98         WriteThreadId(stream_, sample.threadInfo.threadId);
99     }
100     if (buildColdGraph_) {
101         WriteThreadStatus(stream_, sample.threadInfo.threadStatus);
102     }
103     return stream_;
104 }
105 
106 /* override */
ResolveStream(const SampleInfo & sample)107 std::ofstream &MultipleCSVDumper::ResolveStream(const SampleInfo &sample)
108 {
109     auto it = threadIdMap_.find(sample.threadInfo.threadId);
110     if (it == threadIdMap_.end()) {
111         std::string filenameWithThreadId = AddThreadIdToFilename(filename_, sample.threadInfo.threadId);
112 
113         auto returnPair = threadIdMap_.insert({sample.threadInfo.threadId, std::ofstream(filenameWithThreadId)});
114         it = returnPair.first;
115 
116         auto isSuccessInsert = returnPair.second;
117         if (!isSuccessInsert) {
118             LOG(FATAL, PROFILER) << "Failed while insert in unordored_map";
119         }
120     }
121 
122     WriteThreadId(it->second, sample.threadInfo.threadId);
123 
124     if (buildColdGraph_) {
125         WriteThreadStatus(it->second, sample.threadInfo.threadStatus);
126     }
127 
128     return it->second;
129 }
130 
131 /* static */
AddThreadIdToFilename(const std::string & filename,uint32_t threadId)132 std::string MultipleCSVDumper::AddThreadIdToFilename(const std::string &filename, uint32_t threadId)
133 {
134     std::string filenameWithThreadId(filename);
135 
136     std::size_t pos = filenameWithThreadId.find("csv");
137     if (pos == std::string::npos) {
138         LOG(FATAL, PROFILER) << "Incorrect output filename, *.csv format expected";
139     }
140 
141     filenameWithThreadId.insert(pos - 1, std::to_string(threadId));
142 
143     return filenameWithThreadId;
144 }
145 
146 }  // namespace ark::tooling::sampler
147