• 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 (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> &paramsInfo) 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