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 32using namespace OHOS::HiviewDFX; 33using namespace OHOS::HiviewDFX::UCollectUtil; 34using namespace OHOS::HiviewDFX::UCollect; 35 36namespace OHOS { 37namespace SmartPerf { 38bool g_flagFirst = false; 39std::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}; 56std::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 83void RAM::ThreadGetPss() const 84{ 85 std::map<std::string, std::string> procRamInfo = RAM::GetRamInfo(); 86 procRamInfoLast = procRamInfo; 87} 88 89void RAM::TriggerGetPss() const 90{ 91 auto tStart = std::thread([this]() { 92 this->ThreadGetPss(); 93 }); 94 tStart.detach(); 95} 96 97void RAM::SetFirstFlag() 98{ 99 g_flagFirst = false; 100} 101 102std::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 123std::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 138void RAM::SetPackageName(const std::string &pName) 139{ 140 packageName = pName; 141} 142 143void RAM::SetProcessId(const std::string &pid) 144{ 145 processId = pid; 146} 147 148std::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} 166 167std::map<std::string, std::string> RAM::GetPssRamInfo(FILE *fd, std::vector<std::string> paramsInfo) const 168{ 169 std::map<std::string, std::string> pssRamInfo = ParsePssValues(fd, paramsInfo); 170 std::map<std::string, std::string> sumRamInfo = SaveSumRamInfo(paramsInfo); 171 pssRamInfo.insert(sumRamInfo.cbegin(), sumRamInfo.cend()); 172 if (paramsInfo.empty()) { 173 for (auto &pss : pssRamInfo) { 174 pss.second = "0"; 175 } 176 return pssRamInfo; 177 } 178 return pssRamInfo; 179} 180 181std::map<std::string, std::string> RAM::ParsePssValues(FILE *fd, std::vector<std::string> ¶msInfo) const 182{ 183 std::map<std::string, std::string> pssRamInfo; 184 std::string gpuPssValue = "0"; 185 std::string graphicPssValue = "0"; 186 std::string arktsHeapPssValue = "0"; 187 std::string nativeHeapPssValue = "0"; 188 std::string stackPssValue = "0"; 189 const int paramEleven = 11; 190 char buf[1024] = {'\0'}; 191 while ((fgets(buf, sizeof(buf), fd)) != nullptr) { 192 std::string line = buf; 193 if (line[0] == '-') { 194 continue; 195 } 196 std::vector<std::string> params; 197 SPUtils::StrSplit(line, " ", params); 198 if (params.size() == paramEleven && params[0].find("GL") != std::string::npos) { 199 gpuPssValue = params[1]; 200 } 201 if (params.size() == paramEleven && params[0].find("Graph") != std::string::npos) { 202 graphicPssValue = params[1]; 203 } 204 if (params[0].find("ark") != std::string::npos) { 205 arktsHeapPssValue = params[RAM_THIRD]; 206 } 207 if (params[0].find("native") != std::string::npos && params[1].find("heap") != std::string::npos) { 208 nativeHeapPssValue = params[RAM_SECOND]; 209 } 210 if (params.size() == paramEleven && params[0].find("stack") != std::string::npos) { 211 stackPssValue = params[1]; 212 } 213 if (params.size() == paramEleven && params[0].find("Total") != std::string::npos) { 214 paramsInfo = params; 215 } 216 if (paramsInfo.size() > 0) { 217 break; 218 } 219 } 220 pclose(fd); 221 pssRamInfo["gpuPss"] = gpuPssValue; 222 pssRamInfo["graphicPss"] = graphicPssValue; 223 pssRamInfo["arktsHeapPss"] = arktsHeapPssValue; 224 pssRamInfo["nativeHeapPss"] = nativeHeapPssValue; 225 pssRamInfo["stackPss"] = stackPssValue; 226 return pssRamInfo; 227} 228 229std::map<std::string, std::string> RAM::SaveSumRamInfo(std::vector<std::string> paramsInfo) const 230{ 231 std::map<std::string, std::string> sumRamInfo; 232 if (paramsInfo.empty()) { 233 sumRamInfo = ProcMemNaInfo(); 234 for (auto &sumRam : sumRamInfo) { 235 sumRam.second = "0"; 236 } 237 return sumRamInfo; 238 } 239 sumRamInfo["pss"] = paramsInfo[RAM_ONE]; 240 sumRamInfo["sharedClean"] = paramsInfo[RAM_SECOND]; 241 sumRamInfo["sharedDirty"] = paramsInfo[RAM_THIRD]; 242 sumRamInfo["privateClean"] = paramsInfo[RAM_FOURTH]; 243 sumRamInfo["privateDirty"] = paramsInfo[RAM_FIFTH]; 244 sumRamInfo["swap"] = paramsInfo[RAM_SIXTH]; 245 sumRamInfo["swapPss"] = paramsInfo[RAM_SEVENTH]; 246 sumRamInfo["heapSize"] = paramsInfo[RAM_EIGHTH]; 247 sumRamInfo["heapAlloc"] = paramsInfo[RAM_NINTH]; 248 sumRamInfo["heapFree"] = paramsInfo[RAM_TENTH].erase(static_cast<int>(paramsInfo[RAM_TENTH].size()) - 1); 249 return sumRamInfo; 250} 251} 252} 253