1 /*
2 * Copyright (C) 2021 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 #include "include/RAM.h"
16 #include <sstream>
17 #include <fstream>
18 #include <climits>
19 #include <cstdio>
20 #include <algorithm>
21 #include <iostream>
22 #include <thread>
23 #include <string>
24 #include <regex>
25 #include "include/sp_utils.h"
26 #include "memory_collector.h"
27 #include "collect_result.h"
28 #include "include/startup_delay.h"
29 #include "include/sp_log.h"
30 #include "include/common.h"
31
32 using namespace OHOS::HiviewDFX;
33 using namespace OHOS::HiviewDFX::UCollectUtil;
34 using namespace OHOS::HiviewDFX::UCollect;
35
36 namespace OHOS {
37 namespace SmartPerf {
38 bool g_flagFirst = false;
39 std::map<std::string, std::string> procRamInfoLast {
40 {"pss", "NA"},
41 {"gpuPss", "NA"},
42 {"graphicPss", "NA"},
43 {"arktsHeapPss", "NA"},
44 {"nativeHeapPss", "NA"},
45 {"stackPss", "NA"},
46 {"sharedClean", "NA"},
47 {"sharedDirty", "NA"},
48 {"privateClean", "NA"},
49 {"privateDirty", "NA"},
50 {"swap", "NA"},
51 {"swapPss", "NA"},
52 {"heapSize", "NA"},
53 {"heapAlloc", "NA"},
54 {"heapFree", "NA"},
55 };
ItemData()56 std::map<std::string, std::string> RAM::ItemData()
57 {
58 std::map<std::string, std::string> result;
59 std::map<std::string, std::string> sysRamInfo = RAM::GetSysRamInfo();
60 for (auto it = sysRamInfo.begin(); it != sysRamInfo.end(); ++it) {
61 LOGD("sysRamInfo: key = %s, value = %s", it -> first.c_str(), it -> second.c_str());
62 result.insert(*it);
63 }
64 if (!processId.empty()) {
65 if (g_flagFirst) {
66 RAM::TriggerGetPss();
67 } else {
68 procRamInfoLast = RAM::GetRamInfo();
69 g_flagFirst = true;
70 }
71 for (auto it = procRamInfoLast.begin(); it != procRamInfoLast.end(); ++it) {
72 LOGD("procRamInfoLast: key = %s, value = %s", it -> first.c_str(), it -> second.c_str());
73 result.insert(*it);
74 }
75 } else if (!packageName.empty() && processId.empty()) {
76 std::map<std::string, std::string> procMemInfo = RAM::ProcMemNaInfo();
77 for (auto it = procMemInfo.begin(); it != procMemInfo.end(); ++it) {
78 result.insert(*it);
79 }
80 }
81 LOGD("RAM::ItemData map size(%u)", result.size());
82 return result;
83 }
84
ThreadGetPss() const85 void RAM::ThreadGetPss() const
86 {
87 std::map<std::string, std::string> procRamInfo = RAM::GetRamInfo();
88 procRamInfoLast = procRamInfo;
89 }
90
TriggerGetPss() const91 void RAM::TriggerGetPss() const
92 {
93 auto tStart = std::thread([this]() {
94 this->ThreadGetPss();
95 });
96 tStart.detach();
97 }
98
SetFirstFlag()99 void RAM::SetFirstFlag()
100 {
101 g_flagFirst = false;
102 }
103
ProcMemNaInfo() const104 std::map<std::string, std::string> RAM::ProcMemNaInfo() const
105 {
106 std::map<std::string, std::string> procMemInfo;
107 procMemInfo["arktsHeapPss"] = "NA";
108 procMemInfo["gpuPss"] = "NA";
109 procMemInfo["graphicPss"] = "NA";
110 procMemInfo["heapAlloc"] = "NA";
111 procMemInfo["heapFree"] = "NA";
112 procMemInfo["heapSize"] = "NA";
113 procMemInfo["nativeHeapPss"] = "NA";
114 procMemInfo["privateClean"] = "NA";
115 procMemInfo["privateDirty"] = "NA";
116 procMemInfo["pss"] = "NA";
117 procMemInfo["sharedClean"] = "NA";
118 procMemInfo["sharedDirty"] = "NA";
119 procMemInfo["stackPss"] = "NA";
120 procMemInfo["swap"] = "NA";
121 procMemInfo["swapPss"] = "NA";
122 return procMemInfo;
123 }
124
GetSysRamInfo() const125 std::map<std::string, std::string> RAM::GetSysRamInfo() const
126 {
127 std::map<std::string, std::string> sysRamInfo;
128 std::shared_ptr<MemoryCollector> collector = MemoryCollector::Create();
129 if (collector == nullptr) {
130 LOGE("RAM::GetSysRamInfo collector is nullptr!");
131 return sysRamInfo;
132 }
133 CollectResult<SysMemory> result = collector->CollectSysMemory();
134 sysRamInfo["memTotal"] = std::to_string(result.data.memTotal);
135 sysRamInfo["memFree"] = std::to_string(result.data.memFree);
136 sysRamInfo["memAvailable"] = std::to_string(result.data.memAvailable);
137 return sysRamInfo;
138 }
139
SetPackageName(const std::string & pName)140 void RAM::SetPackageName(const std::string &pName)
141 {
142 packageName = pName;
143 }
144
SetProcessId(const std::string & pid)145 void RAM::SetProcessId(const std::string &pid)
146 {
147 processId = pid;
148 }
149
GetRamInfo() const150 std::map<std::string, std::string> RAM::GetRamInfo() const
151 {
152 std::map<std::string, std::string> procRamInfo;
153 std::string pssValue = "";
154 std::string cmd = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_MEM) + processId;
155 FILE *fd = popen(cmd.c_str(), "r");
156 if (fd == nullptr) {
157 LOGD("RAM::fd is empty");
158 procRamInfo = ProcMemNaInfo();
159 for (auto item : procRamInfo) {
160 item.second = "0";
161 }
162 return procRamInfo;
163 }
164 std::vector<std::string> paramsInfo;
165 procRamInfo = GetPssRamInfo(fd, paramsInfo);
166 for (const auto& value : paramsInfo) {
167 if (procRamInfo[value].empty()) {
168 procRamInfo[value] = "0";
169 }
170 }
171 int closeStatus = pclose(fd);
172 if (closeStatus == -1) {
173 LOGE("Error: Failed to close file");
174 return {};
175 }
176 return procRamInfo;
177 }
178
GetPssRamInfo(FILE * fd,std::vector<std::string> paramsInfo) const179 std::map<std::string, std::string> RAM::GetPssRamInfo(FILE *fd, std::vector<std::string> paramsInfo) const
180 {
181 std::map<std::string, std::string> pssRamInfo = ParsePssValues(fd, paramsInfo);
182 std::map<std::string, std::string> sumRamInfo = SaveSumRamInfo(paramsInfo);
183 pssRamInfo.insert(sumRamInfo.cbegin(), sumRamInfo.cend());
184 if (paramsInfo.empty()) {
185 for (auto &pss : pssRamInfo) {
186 pss.second = "0";
187 }
188 return pssRamInfo;
189 }
190 return pssRamInfo;
191 }
192
ParsePssValues(FILE * fd,std::vector<std::string> & paramsInfo) const193 std::map<std::string, std::string> RAM::ParsePssValues(FILE *fd, std::vector<std::string> ¶msInfo) const
194 {
195 std::map<std::string, std::string> pssRamInfo;
196 std::string gpuPssValue = "";
197 std::string graphicPssValue = "";
198 std::string arktsHeapPssValue = "";
199 std::string nativeHeapPssValue = "";
200 std::string stackPssValue = "";
201 char buf[1024] = {'\0'};
202 while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
203 std::string line(buf);
204 LOGD("ParsePssValues::line = %s", line.c_str());
205 if (line[0] == '-') {
206 continue;
207 }
208 std::vector<std::string> params;
209 SPUtils::StrSplit(line, " ", params);
210 if (params.size() > RAM_SECOND && params[0].find("GL") != std::string::npos) {
211 gpuPssValue = params[1];
212 }
213 if (params.size() > RAM_SECOND && params[0].find("Graph") != std::string::npos) {
214 graphicPssValue = params[1];
215 }
216 if (params.size() > RAM_FOURTH && params[0].find("ark") != std::string::npos) {
217 arktsHeapPssValue = params[RAM_THIRD];
218 }
219 if (params.size() > RAM_THIRD && params[0].find("native") != std::string::npos &&
220 params[1].find("heap") != std::string::npos) {
221 nativeHeapPssValue = params[RAM_SECOND];
222 }
223 if (params.size() > RAM_SECOND && params[0].find("stack") != std::string::npos) {
224 stackPssValue = params[1];
225 }
226 if (!gpuPssValue.empty() && params.size() > 0 && params[0].find("Total") != std::string::npos) {
227 paramsInfo = params;
228 }
229 if (paramsInfo.size() > 0) {
230 break;
231 }
232 }
233 pssRamInfo["gpuPss"] = gpuPssValue;
234 pssRamInfo["graphicPss"] = graphicPssValue;
235 pssRamInfo["arktsHeapPss"] = arktsHeapPssValue;
236 pssRamInfo["nativeHeapPss"] = nativeHeapPssValue;
237 pssRamInfo["stackPss"] = stackPssValue;
238 return pssRamInfo;
239 }
SaveSumRamInfo(std::vector<std::string> paramsInfo) const240 std::map<std::string, std::string> RAM::SaveSumRamInfo(std::vector<std::string> paramsInfo) const
241 {
242 std::map<std::string, std::string> sumRamInfo;
243 if (paramsInfo.empty()) {
244 sumRamInfo = ProcMemNaInfo();
245 for (auto &sumRam : sumRamInfo) {
246 sumRam.second = "0";
247 }
248 return sumRamInfo;
249 }
250 std::vector<std::string> sumRamKeys = {"pss", "sharedClean", "sharedDirty", "privateClean",
251 "privateDirty", "swap", "swapPss", "heapSize", "heapAlloc", "heapFree"};
252 for (size_t i = 0; i < paramsInfo.size() - 1 && i < sumRamKeys.size(); i++) {
253 if (i == RAM_NINTH) {
254 sumRamInfo["heapFree"] = paramsInfo[RAM_TENTH].erase(static_cast<int>(paramsInfo[RAM_TENTH].size()) - 1);
255 break;
256 }
257 sumRamInfo[sumRamKeys[i]] = paramsInfo[i + 1];
258 }
259 return sumRamInfo;
260 }
261 }
262 }
263