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 result.insert(*it);
62 }
63 if (!processId.empty()) {
64 if (g_flagFirst) {
65 RAM::TriggerGetPss();
66 } else {
67 procRamInfoLast = RAM::GetRamInfo();
68 g_flagFirst = true;
69 }
70 for (auto it = procRamInfoLast.begin(); it != procRamInfoLast.end(); ++it) {
71 result.insert(*it);
72 }
73 } else if (!packageName.empty() && processId.empty()) {
74 std::map<std::string, std::string> procMemInfo = RAM::ProcMemNaInfo();
75 for (auto it = procMemInfo.begin(); it != procMemInfo.end(); ++it) {
76 result.insert(*it);
77 }
78 }
79 LOGI("RAM::ItemData map size(%u)", result.size());
80 return result;
81 }
82
ThreadGetPss() const83 void RAM::ThreadGetPss() const
84 {
85 std::map<std::string, std::string> procRamInfo = RAM::GetRamInfo();
86 procRamInfoLast = procRamInfo;
87 }
88
TriggerGetPss() const89 void RAM::TriggerGetPss() const
90 {
91 auto tStart = std::thread([this]() {
92 this->ThreadGetPss();
93 });
94 tStart.detach();
95 }
96
SetFirstFlag()97 void RAM::SetFirstFlag()
98 {
99 g_flagFirst = false;
100 }
101
ProcMemNaInfo() const102 std::map<std::string, std::string> RAM::ProcMemNaInfo() const
103 {
104 std::map<std::string, std::string> procMemInfo;
105 procMemInfo["arktsHeapPss"] = "NA";
106 procMemInfo["gpuPss"] = "NA";
107 procMemInfo["graphicPss"] = "NA";
108 procMemInfo["heapAlloc"] = "NA";
109 procMemInfo["heapFree"] = "NA";
110 procMemInfo["heapSize"] = "NA";
111 procMemInfo["nativeHeapPss"] = "NA";
112 procMemInfo["privateClean"] = "NA";
113 procMemInfo["privateDirty"] = "NA";
114 procMemInfo["pss"] = "NA";
115 procMemInfo["sharedClean"] = "NA";
116 procMemInfo["sharedDirty"] = "NA";
117 procMemInfo["stackPss"] = "NA";
118 procMemInfo["swap"] = "NA";
119 procMemInfo["swapPss"] = "NA";
120 return procMemInfo;
121 }
122
GetSysRamInfo() const123 std::map<std::string, std::string> RAM::GetSysRamInfo() const
124 {
125 std::map<std::string, std::string> sysRamInfo;
126 std::shared_ptr<MemoryCollector> collector = MemoryCollector::Create();
127 if (collector == nullptr) {
128 LOGE("RAM::GetSysRamInfo collector is nullptr!");
129 return sysRamInfo;
130 }
131 CollectResult<SysMemory> result = collector->CollectSysMemory();
132 sysRamInfo["memTotal"] = std::to_string(result.data.memTotal);
133 sysRamInfo["memFree"] = std::to_string(result.data.memFree);
134 sysRamInfo["memAvailable"] = std::to_string(result.data.memAvailable);
135 return sysRamInfo;
136 }
137
SetPackageName(const std::string & pName)138 void RAM::SetPackageName(const std::string &pName)
139 {
140 packageName = pName;
141 }
142
SetProcessId(const std::string & pid)143 void RAM::SetProcessId(const std::string &pid)
144 {
145 processId = pid;
146 }
147
GetRamInfo() const148 std::map<std::string, std::string> RAM::GetRamInfo() const
149 {
150 std::map<std::string, std::string> procRamInfo;
151 std::string pssValue = "";
152 std::string cmd = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_MEM) + processId;
153 FILE *fd = popen(cmd.c_str(), "r");
154 if (fd == nullptr) {
155 return procRamInfo;
156 }
157 std::vector<std::string> paramsInfo;
158 procRamInfo = GetPssRamInfo(fd, paramsInfo);
159 for (const auto& value : paramsInfo) {
160 if (procRamInfo[value].empty()) {
161 procRamInfo[value] = "0";
162 }
163 }
164 return procRamInfo;
165 }
GetPssRamInfo(FILE * fd,std::vector<std::string> paramsInfo) const166 std::map<std::string, std::string> RAM::GetPssRamInfo(FILE *fd, std::vector<std::string> paramsInfo) const
167 {
168 std::map<std::string, std::string> pssRamInfo;
169 std::string gpuPssValue = "";
170 std::string graphicPssValue = "";
171 std::string arktsHeapPssValue = "";
172 std::string nativeHeapPssValue = "";
173 std::string stackPssValue = "";
174 const int paramEleven = 11;
175 char buf[1024] = {'\0'};
176 while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
177 std::string line = buf;
178 if (line[0] == '-') {
179 continue;
180 }
181 std::vector<std::string> params;
182 SPUtils::StrSplit(line, " ", params);
183 if (params.size() == paramEleven && params[0].find("GL") != std::string::npos) {
184 gpuPssValue = params[1];
185 }
186 if (params.size() == paramEleven && params[0].find("Graph") != std::string::npos) {
187 graphicPssValue = params[1];
188 }
189 if (params[0].find("ark") != std::string::npos) {
190 arktsHeapPssValue = params[RAM_THIRD];
191 }
192 if (params[0].find("native") != std::string::npos && params[1].find("heap") != std::string::npos) {
193 nativeHeapPssValue = params[RAM_SECOND];
194 }
195 if (params.size() == paramEleven && params[0].find("stack") != std::string::npos) {
196 stackPssValue = params[1];
197 }
198 if (params.size() == paramEleven && params[0].find("Total") != std::string::npos) {
199 paramsInfo = params;
200 }
201 if (paramsInfo.size() > 0) {
202 break;
203 }
204 }
205 pclose(fd);
206 std::map<std::string, std::string> sumRamInfo = SaveSumRamInfo(paramsInfo);
207 pssRamInfo.insert(sumRamInfo.cbegin(), sumRamInfo.cend());
208 pssRamInfo["gpuPss"] = gpuPssValue;
209 pssRamInfo["graphicPss"] = graphicPssValue;
210 pssRamInfo["arktsHeapPss"] = arktsHeapPssValue;
211 pssRamInfo["nativeHeapPss"] = nativeHeapPssValue;
212 pssRamInfo["stackPss"] = stackPssValue;
213 return pssRamInfo;
214 }
SaveSumRamInfo(std::vector<std::string> paramsInfo) const215 std::map<std::string, std::string> RAM::SaveSumRamInfo(std::vector<std::string> paramsInfo) const
216 {
217 std::map<std::string, std::string> sumRamInfo;
218 if (paramsInfo.empty()) {
219 return sumRamInfo;
220 }
221 sumRamInfo["pss"] = paramsInfo[RAM_ONE];
222 sumRamInfo["sharedClean"] = paramsInfo[RAM_SECOND];
223 sumRamInfo["sharedDirty"] = paramsInfo[RAM_THIRD];
224 sumRamInfo["privateClean"] = paramsInfo[RAM_FOURTH];
225 sumRamInfo["privateDirty"] = paramsInfo[RAM_FIFTH];
226 sumRamInfo["swap"] = paramsInfo[RAM_SIXTH];
227 sumRamInfo["swapPss"] = paramsInfo[RAM_SEVENTH];
228 sumRamInfo["heapSize"] = paramsInfo[RAM_EIGHTH];
229 sumRamInfo["heapAlloc"] = paramsInfo[RAM_NINTH];
230 sumRamInfo["heapFree"] = paramsInfo[RAM_TENTH].erase(static_cast<int>(paramsInfo[RAM_TENTH].size()) - 1);
231 return sumRamInfo;
232 }
233 }
234 }
235