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 (const auto& item : sysRamInfo) {
61 result.insert(item);
62 }
63 if (!processId.empty()) {
64 std::map<std::string, std::string> procRamInfomation;
65 if (g_flagFirst) {
66 RAM::TriggerGetPss();
67 } else {
68 procRamInfoLast = RAM::GetRamInfo();
69 g_flagFirst = true;
70 }
71 if (!procRamInfoLast.empty()) {
72 procRamInfomation = procRamInfoLast;
73 for (const auto& item : procRamInfomation) {
74 result.insert(item);
75 }
76 } else {
77 procRamInfomation = ProcMemNaInfo();
78 for (const auto& item : procRamInfomation) {
79 result.insert(item);
80 }
81 }
82 } else if (!packageName.empty() && processId.empty()) {
83 std::map<std::string, std::string> procMemInfo = RAM::ProcMemNaInfo();
84 for (const auto& item : procMemInfo) {
85 result.insert(item);
86 }
87 }
88 return result;
89 }
90
ThreadGetPss() const91 void RAM::ThreadGetPss() const
92 {
93 std::map<std::string, std::string> procRamInfo = RAM::GetRamInfo();
94 procRamInfoLast = procRamInfo;
95 }
96
TriggerGetPss() const97 void RAM::TriggerGetPss() const
98 {
99 auto tStart = std::thread([this]() {
100 this->ThreadGetPss();
101 });
102 tStart.detach();
103 }
104
SetFirstFlag()105 void RAM::SetFirstFlag()
106 {
107 g_flagFirst = false;
108 }
109
SetHapFirstFlag()110 void RAM::SetHapFirstFlag()
111 {
112 g_flagFirst = true;
113 }
114
ProcMemNaInfo() const115 std::map<std::string, std::string> RAM::ProcMemNaInfo() const
116 {
117 std::map<std::string, std::string> procMemInfo;
118 procMemInfo["arktsHeapPss"] = "NA";
119 procMemInfo["gpuPss"] = "NA";
120 procMemInfo["graphicPss"] = "NA";
121 procMemInfo["heapAlloc"] = "NA";
122 procMemInfo["heapFree"] = "NA";
123 procMemInfo["heapSize"] = "NA";
124 procMemInfo["nativeHeapPss"] = "NA";
125 procMemInfo["privateClean"] = "NA";
126 procMemInfo["privateDirty"] = "NA";
127 procMemInfo["pss"] = "NA";
128 procMemInfo["sharedClean"] = "NA";
129 procMemInfo["sharedDirty"] = "NA";
130 procMemInfo["stackPss"] = "NA";
131 procMemInfo["swap"] = "NA";
132 procMemInfo["swapPss"] = "NA";
133 return procMemInfo;
134 }
135
GetSysRamInfo() const136 std::map<std::string, std::string> RAM::GetSysRamInfo() const
137 {
138 std::map<std::string, std::string> sysRamInfo;
139 std::shared_ptr<MemoryCollector> collector = MemoryCollector::Create();
140 if (collector == nullptr) {
141 LOGE("RAM::GetSysRamInfo collector is nullptr!");
142 return sysRamInfo;
143 }
144 CollectResult<SysMemory> result = collector->CollectSysMemory();
145 sysRamInfo["memTotal"] = std::to_string(result.data.memTotal);
146 sysRamInfo["memFree"] = std::to_string(result.data.memFree);
147 sysRamInfo["memAvailable"] = std::to_string(result.data.memAvailable);
148 //整机内存信息
149 LOGD("sysRamInfo map size(%u)", sysRamInfo.size());
150 return sysRamInfo;
151 }
152
SetPackageName(const std::string & pName)153 void RAM::SetPackageName(const std::string &pName)
154 {
155 packageName = pName;
156 }
157
SetProcessId(const std::string & pid)158 void RAM::SetProcessId(const std::string &pid)
159 {
160 processId = pid;
161 }
162
GetRamInfo() const163 std::map<std::string, std::string> RAM::GetRamInfo() const
164 {
165 std::map<std::string, std::string> procRamInfo;
166 std::map<std::string, std::string> emptyprocRamInfo;
167 std::string pssValue = "";
168 std::string cmd = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_MEM) + processId;
169 if (cmd.empty()) {
170 LOGE("RAM::GetRamInfo cmd is null");
171 return emptyprocRamInfo;
172 }
173 FILE *fd = popen(cmd.c_str(), "r");
174 if (fd == nullptr) {
175 LOGD("RAM::fd is empty");
176 emptyprocRamInfo = ProcMemNaInfo();
177 for (auto item : emptyprocRamInfo) {
178 item.second = "0";
179 }
180 return emptyprocRamInfo;
181 }
182 std::vector<std::string> paramsInfo;
183 procRamInfo = GetPssRamInfo(fd, paramsInfo);
184 if (procRamInfo.empty()) {
185 return emptyprocRamInfo;
186 }
187 for (const auto& value : paramsInfo) {
188 if (procRamInfo[value].empty()) {
189 procRamInfo[value] = "0";
190 }
191 }
192 int closeStatus = pclose(fd);
193 if (closeStatus == -1) {
194 LOGE("Error: Failed to close file");
195 return emptyprocRamInfo;
196 }
197 return procRamInfo;
198 }
199
GetPssRamInfo(FILE * fd,std::vector<std::string> paramsInfo) const200 std::map<std::string, std::string> RAM::GetPssRamInfo(FILE *fd, std::vector<std::string> paramsInfo) const
201 {
202 std::map<std::string, std::string> pssRamInfo = ParsePssValues(fd, paramsInfo);
203 std::map<std::string, std::string> sumRamInfo = SaveSumRamInfo(paramsInfo);
204 pssRamInfo.insert(sumRamInfo.cbegin(), sumRamInfo.cend());
205 if (paramsInfo.empty()) {
206 for (auto &pss : pssRamInfo) {
207 pss.second = "0";
208 }
209 return pssRamInfo;
210 }
211 return pssRamInfo;
212 }
213
ParsePssValues(FILE * fd,std::vector<std::string> & paramsInfo) const214 std::map<std::string, std::string> RAM::ParsePssValues(FILE *fd, std::vector<std::string> ¶msInfo) const
215 {
216 std::map<std::string, std::string> pssRamInfo;
217 std::string gpuPssValue = "";
218 std::string graphicPssValue = "";
219 std::string arktsHeapPssValue = "";
220 std::string nativeHeapPssValue = "";
221 std::string stackPssValue = "";
222 char buf[1024] = {'\0'};
223 while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
224 std::string line(buf);
225 LOGD("ParsePssValues::line = %s", line.c_str());
226 if (line[0] == '-') {
227 continue;
228 }
229 std::vector<std::string> params;
230 SPUtils::StrSplit(line, " ", params);
231 if (params.size() > RAM_SECOND && params[0].find("GL") != std::string::npos) {
232 gpuPssValue = params[1];
233 }
234 if (params.size() > RAM_SECOND && params[0].find("Graph") != std::string::npos) {
235 graphicPssValue = params[1];
236 }
237 if (params.size() > RAM_FOURTH && params[0].find("ark") != std::string::npos) {
238 arktsHeapPssValue = params[RAM_THIRD];
239 }
240 if (params.size() > RAM_THIRD && params[0].find("native") != std::string::npos &&
241 params[1].find("heap") != std::string::npos) {
242 nativeHeapPssValue = params[RAM_SECOND];
243 }
244 if (params.size() > RAM_SECOND && params[0].find("stack") != std::string::npos) {
245 stackPssValue = params[1];
246 }
247 if (!gpuPssValue.empty() && params.size() > 0 && params[0].find("Total") != std::string::npos) {
248 paramsInfo = params;
249 }
250 if (paramsInfo.size() > 0) {
251 break;
252 }
253 }
254 pssRamInfo["gpuPss"] = gpuPssValue;
255 pssRamInfo["graphicPss"] = graphicPssValue;
256 pssRamInfo["arktsHeapPss"] = arktsHeapPssValue;
257 pssRamInfo["nativeHeapPss"] = nativeHeapPssValue;
258 pssRamInfo["stackPss"] = stackPssValue;
259 //应用程序的内存占用信息
260 LOGD("pssRamInfo map size(%u)", pssRamInfo.size());
261 return pssRamInfo;
262 }
SaveSumRamInfo(std::vector<std::string> paramsInfo) const263 std::map<std::string, std::string> RAM::SaveSumRamInfo(std::vector<std::string> paramsInfo) const
264 {
265 std::map<std::string, std::string> sumRamInfo;
266 if (paramsInfo.empty()) {
267 sumRamInfo = ProcMemNaInfo();
268 for (auto &sumRam : sumRamInfo) {
269 sumRam.second = "0";
270 }
271 return sumRamInfo;
272 }
273 std::vector<std::string> sumRamKeys = {"pss", "sharedClean", "sharedDirty", "privateClean",
274 "privateDirty", "swap", "swapPss", "heapSize", "heapAlloc", "heapFree"};
275 for (size_t i = 0; i < paramsInfo.size() - 1 && i < sumRamKeys.size(); i++) {
276 if (i == RAM_NINTH) {
277 sumRamInfo["heapFree"] = paramsInfo[RAM_TENTH].erase(static_cast<int>(paramsInfo[RAM_TENTH].size()) - 1);
278 break;
279 }
280 sumRamInfo[sumRamKeys[i]] = paramsInfo[i + 1];
281 }
282 //应用程序的内存消耗信息
283 LOGD("sumRamInfo map size(%u)", sumRamInfo.size());
284 return sumRamInfo;
285 }
286 }
287 }
288