• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "sample_stack_printer.h"
17 
18 #include <iostream>
19 #include <sstream>
20 
21 #include "dfx_frame_formatter.h"
22 #include "thread_sampler_utils.h"
23 
24 namespace OHOS {
25 namespace HiviewDFX {
Insert(SampleStackItem * curNode,uintptr_t pc,int32_t count,uint64_t level)26 SampleStackItem* SampleStackPrinter::Insert(SampleStackItem* curNode, uintptr_t pc, int32_t count, uint64_t level)
27 {
28     if (curNode == nullptr) {
29         return nullptr;
30     }
31 
32     if (curNode->pc == pc) {
33         curNode->count += count;
34         return curNode;
35     }
36 
37     if (curNode->pc == 0) {
38         curNode->pc = pc;
39         curNode->count += count;
40         curNode->current = std::make_shared<DfxFrame>();
41         curNode->current->index = curNode->level;
42 
43         unwinder_->GetFrameByPc(pc, maps_, *(curNode->current));
44         return curNode;
45     }
46 
47     if (level > curNode->level) {
48         if (curNode->child == nullptr) {
49             curNode->child = new SampleStackItem;
50             curNode->child->level = curNode->level + 1;
51             allNodes_.push_back(curNode->child);
52             return Insert(curNode->child, pc, count, level);
53         }
54 
55         if (curNode->child->pc == pc) {
56             curNode->child->count += count;
57             return curNode->child;
58         }
59 
60         curNode = curNode->child;
61     }
62 
63     if (curNode->siblings == nullptr) {
64         curNode->siblings = new SampleStackItem;
65         curNode->siblings->level = curNode->level;
66         allNodes_.push_back(curNode->siblings);
67         return Insert(curNode->siblings, pc, count, level);
68     }
69 
70     if (curNode->siblings->pc == pc) {
71         curNode->siblings->count += count;
72         return curNode->siblings;
73     }
74 
75     return Insert(curNode->siblings, pc, count, level);
76 }
77 
Insert(std::vector<uintptr_t> & pcs,int32_t count)78 void SampleStackPrinter::Insert(std::vector<uintptr_t>& pcs, int32_t count)
79 {
80     if (root_ == nullptr) {
81         root_ = new SampleStackItem;
82         root_->level = 0;
83         allNodes_.push_back(root_);
84     }
85 
86     SampleStackItem* curNode = root_;
87     uint64_t level = 0;
88     for (auto iter = pcs.rbegin(); iter != pcs.rend(); ++iter) {
89         curNode = Insert(curNode, *iter, count, level);
90         level++;
91     }
92 }
93 
GetFullStack(std::vector<TimeAndFrames> & timeAndFrameList)94 std::string SampleStackPrinter::GetFullStack(std::vector<TimeAndFrames>& timeAndFrameList)
95 {
96     std::string stack("");
97     for (auto& taf : timeAndFrameList) {
98         std::string requestTimeStr = TimeFormat(taf.requestTime);
99         std::string snapshotTimeStr = TimeFormat(taf.snapshotTime);
100         if (requestTimeStr == "" || snapshotTimeStr == "") {
101             return stack;
102         }
103         stack += ("RequestTime:" + requestTimeStr + "\nSnapshotTime:" + snapshotTimeStr + "\n");
104         std::vector<DfxFrame> frames = taf.frameList;
105         for (auto& frame : frames) {
106             unwinder_->FillFrame(frame);
107             auto frameStr = DfxFrameFormatter::GetFrameStr(frame);
108             stack += frameStr;
109         }
110         stack += "\n";
111     }
112     return stack;
113 }
114 
GetTreeStack(std::map<uint64_t,std::vector<uint64_t>> & stackIdTimeMap,std::unique_ptr<UniqueStackTable> & uniqueStackTable)115 std::string SampleStackPrinter::GetTreeStack(std::map<uint64_t, std::vector<uint64_t>>& stackIdTimeMap,
116     std::unique_ptr<UniqueStackTable>& uniqueStackTable)
117 {
118     std::vector<std::pair<uint64_t, uint64_t>> sortedStackId;
119     for (auto it = stackIdTimeMap.begin(); it != stackIdTimeMap.end(); it++) {
120         uint64_t stackId = it->first;
121         sortedStackId.emplace_back(std::make_pair<uint64_t, uint64_t>(std::move(stackId), it->second.size()));
122         std::sort(sortedStackId.begin(), sortedStackId.end(), [](auto& a, auto& b) {
123             return a.second > b.second;
124         });
125     }
126     for (auto it = sortedStackId.begin(); it != sortedStackId.end(); it++) {
127         std::vector<uintptr_t> pcs;
128         OHOS::HiviewDFX::StackId stackId;
129         stackId.value = it->first;
130         if (uniqueStackTable->GetPcsByStackId(stackId, pcs)) {
131             Insert(pcs, it->second);
132         }
133     }
134     std::string stack = Print();
135     return stack;
136 }
137 
Print()138 std::string SampleStackPrinter::Print()
139 {
140     if (root_ == nullptr) {
141         return std::string("");
142     }
143 
144     std::stringstream ret;
145     std::vector<SampleStackItem*> nodes;
146     nodes.push_back(root_);
147     const int indent = 2;
148     while (!nodes.empty()) {
149         SampleStackItem* back = nodes.back();
150         SampleStackItem* sibling = back->siblings;
151         SampleStackItem* child = back->child;
152         std::string space(indent * back->level, ' ');
153         nodes.pop_back();
154 
155         ret << space << back->count << " " << DfxFrameFormatter::GetFrameStr(back->current);
156         if (sibling != nullptr) {
157             nodes.push_back(sibling);
158         }
159 
160         if (child != nullptr) {
161             nodes.push_back(child);
162         }
163     }
164     return ret.str();
165 }
166 
FreeNodes()167 void SampleStackPrinter::FreeNodes()
168 {
169     for (auto node : allNodes_) {
170         if (node != nullptr) {
171             delete node;
172         }
173     }
174     allNodes_.clear();
175     allNodes_.shrink_to_fit();
176 }
177 } // end of namespace HiviewDFX
178 } // end of namespace OHOS
179