• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &paramsInfo) 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