• 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             fullMethodName = "System_Frame";
31         } else {
32             const panda_file::File *pf = nullptr;
33             auto it = modulesMap_->find(pfId);
34             if (it != modulesMap_->end()) {
35                 pf = it->second.get();
36             }
37 
38             fullMethodName = ResolveName(pf, fileId);
39         }
40         stream << fullMethodName << "; ";
41     }
42     stream << count << "\n";
43 }
44 
45 /* static */
WriteThreadId(std::ofstream & stream,uint32_t threadId)46 void TraceDumper::WriteThreadId(std::ofstream &stream, uint32_t threadId)
47 {
48     stream << "thread_id = " << threadId << "; ";
49 }
50 
51 /* static */
WriteThreadStatus(std::ofstream & stream,SampleInfo::ThreadStatus threadStatus)52 void TraceDumper::WriteThreadStatus(std::ofstream &stream, SampleInfo::ThreadStatus threadStatus)
53 {
54     stream << "status = ";
55 
56     switch (threadStatus) {
57         case SampleInfo::ThreadStatus::RUNNING: {
58             stream << "active; ";
59             break;
60         }
61         case SampleInfo::ThreadStatus::SUSPENDED: {
62             stream << "suspended; ";
63             break;
64         }
65         default: {
66             UNREACHABLE();
67         }
68     }
69 }
70 
ResolveName(const panda_file::File * pf,uint64_t fileId) const71 std::string TraceDumper::ResolveName(const panda_file::File *pf, uint64_t fileId) const
72 {
73     if (pf == nullptr) {
74         return std::string("__unknown_module::" + std::to_string(fileId));
75     }
76 
77     auto it = methodsMap_->find(pf);
78     if (it != methodsMap_->end()) {
79         return it->second.at(fileId);
80     }
81 
82     return pf->GetFilename() + "::__unknown_" + std::to_string(fileId);
83 }
84 
85 /* override */
ResolveStream(const SampleInfo & sample)86 std::ofstream &SingleCSVDumper::ResolveStream(const SampleInfo &sample)
87 {
88     if (option_ == DumpType::THREAD_SEPARATION_BY_TID) {
89         WriteThreadId(stream_, sample.threadInfo.threadId);
90     }
91     if (buildColdGraph_) {
92         WriteThreadStatus(stream_, sample.threadInfo.threadStatus);
93     }
94     return stream_;
95 }
96 
97 /* override */
ResolveStream(const SampleInfo & sample)98 std::ofstream &MultipleCSVDumper::ResolveStream(const SampleInfo &sample)
99 {
100     auto it = threadIdMap_.find(sample.threadInfo.threadId);
101     if (it == threadIdMap_.end()) {
102         std::string filenameWithThreadId = AddThreadIdToFilename(filename_, sample.threadInfo.threadId);
103 
104         auto returnPair = threadIdMap_.insert({sample.threadInfo.threadId, std::ofstream(filenameWithThreadId)});
105         it = returnPair.first;
106 
107         auto isSuccessInsert = returnPair.second;
108         if (!isSuccessInsert) {
109             LOG(FATAL, PROFILER) << "Failed while insert in unordored_map";
110         }
111     }
112 
113     WriteThreadId(it->second, sample.threadInfo.threadId);
114 
115     if (buildColdGraph_) {
116         WriteThreadStatus(it->second, sample.threadInfo.threadStatus);
117     }
118 
119     return it->second;
120 }
121 
122 /* static */
AddThreadIdToFilename(const std::string & filename,uint32_t threadId)123 std::string MultipleCSVDumper::AddThreadIdToFilename(const std::string &filename, uint32_t threadId)
124 {
125     std::string filenameWithThreadId(filename);
126 
127     std::size_t pos = filenameWithThreadId.find("csv");
128     if (pos == std::string::npos) {
129         LOG(FATAL, PROFILER) << "Incorrect output filename, *.csv format expected";
130     }
131 
132     filenameWithThreadId.insert(pos - 1, std::to_string(threadId));
133 
134     return filenameWithThreadId;
135 }
136 
137 }  // namespace ark::tooling::sampler
138