1 /*
2 * Copyright (C) 2021-2022 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 "executor/memory/memory_info.h"
16 #include <algorithm>
17 #include <atomic>
18 #include <dlfcn.h>
19 #include <cinttypes>
20 #include <fstream>
21 #include <numeric>
22 #include <sstream>
23 #include <thread>
24 #include <v1_0/imemory_tracker_interface.h>
25
26 #include "dump_common_utils.h"
27 #include "dump_utils.h"
28 #include "executor/memory/get_cma_info.h"
29 #include "executor/memory/get_hardware_info.h"
30 #include "executor/memory/get_kernel_info.h"
31 #include "executor/memory/get_process_info.h"
32 #include "executor/memory/get_ram_info.h"
33 #include "executor/memory/memory_util.h"
34 #include "executor/memory/parse/parse_ashmem_info.h"
35 #include "executor/memory/parse/parse_dmabuf_info.h"
36 #include "executor/memory/parse/parse_meminfo.h"
37 #include "executor/memory/parse/parse_smaps_rollup_info.h"
38 #include "executor/memory/parse/parse_smaps_info.h"
39 #include "file_ex.h"
40 #include "hdf_base.h"
41 #include "hilog_wrapper.h"
42 #ifdef HIDUMPER_MEMMGR_ENABLE
43 #include "mem_mgr_constant.h"
44 #endif
45 #include "securec.h"
46 #include "string_ex.h"
47 #include "util/string_utils.h"
48 #include "util/file_utils.h"
49
50 using namespace std;
51 using namespace OHOS::HDI::Memorytracker::V1_0;
52
53 namespace OHOS {
54 namespace HiviewDFX {
55 static const int PAGETAG_MIN_LEN = 2; // page tag min length
56 static const std::string LIB = "libai_mnt_client.so";
57
58 static const std::string UNKNOWN_PROCESS = "unknown";
59 static const std::string PRE_BLANK = " ";
60 static const std::string MEMORY_LINE = "-------------------------------[memory]-------------------------------";
61 constexpr char HIAI_MEM_INFO_FN[] = "HIAI_Memory_QueryAllUserAllocatedMemInfo";
62 using HiaiFunc = int (*)(MemInfoData::HiaiUserAllocatedMemInfo*, int, int*);
63 std::atomic<bool> g_isDumpMem = true;
64 constexpr int SECOND_TO_MILLISECONDS = 1000;
65 constexpr int MAX_STARS_NUM = 20;
66 constexpr int ONE_STAR = 1;
67 constexpr int APP_UID = 20000;
68 constexpr int LINE_SPACING = 8;
69
MemoryInfo()70 MemoryInfo::MemoryInfo()
71 {
72 methodVec_.clear();
73 methodVec_.push_back(make_pair(MEMINFO_PSS,
74 bind(&MemoryInfo::SetPss, this, placeholders::_1, placeholders::_2)));
75 methodVec_.push_back(make_pair(MEMINFO_SHARED_CLEAN,
76 bind(&MemoryInfo::SetSharedClean, this, placeholders::_1, placeholders::_2)));
77 methodVec_.push_back(make_pair(MEMINFO_SHARED_DIRTY,
78 bind(&MemoryInfo::SetSharedDirty, this, placeholders::_1, placeholders::_2)));
79 methodVec_.push_back(make_pair(MEMINFO_PRIVATE_CLEAN,
80 bind(&MemoryInfo::SetPrivateClean, this, placeholders::_1, placeholders::_2)));
81 methodVec_.push_back(make_pair(MEMINFO_PRIVATE_DIRTY,
82 bind(&MemoryInfo::SetPrivateDirty, this, placeholders::_1, placeholders::_2)));
83 methodVec_.push_back(make_pair(MEMINFO_SWAP,
84 bind(&MemoryInfo::SetSwap, this, placeholders::_1, placeholders::_2)));
85 methodVec_.push_back(make_pair(MEMINFO_SWAP_PSS,
86 bind(&MemoryInfo::SetSwapPss, this, placeholders::_1, placeholders::_2)));
87 methodVec_.push_back(make_pair(MEMINFO_HEAP_SIZE,
88 bind(&MemoryInfo::SetHeapSize, this, placeholders::_1, placeholders::_2)));
89 methodVec_.push_back(make_pair(MEMINFO_HEAP_ALLOC,
90 bind(&MemoryInfo::SetHeapAlloc, this, placeholders::_1, placeholders::_2)));
91 methodVec_.push_back(make_pair(MEMINFO_HEAP_FREE,
92 bind(&MemoryInfo::SetHeapFree, this, placeholders::_1, placeholders::_2)));
93 }
94
~MemoryInfo()95 MemoryInfo::~MemoryInfo()
96 {
97 }
98
InsertMemoryTitle(StringMatrix result)99 void MemoryInfo::InsertMemoryTitle(StringMatrix result)
100 {
101 // Pss Shared ---- this line is line1
102 // Total Clean ---- this line is line2
103 // (KB) (KB) ---- this line is line3
104 // ----- ------ ---- this line is line4
105
106 vector<string> line1;
107 vector<string> line2;
108 vector<string> line3;
109 vector<string> line4;
110
111 string space = " ";
112 StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, space);
113
114 string separator = "-";
115 StringUtils::GetInstance().SetWidth(LINE_WIDTH_, SEPARATOR_, false, separator);
116
117 string unit = "(" + MemoryUtil::GetInstance().KB_UNIT_ + " )";
118 StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, unit);
119
120 // Add spaces at the beginning of the line
121 line1.push_back(space + BLANK_);
122 line2.push_back(space + BLANK_);
123 line3.push_back(space + BLANK_);
124 line4.push_back(space);
125
126 for (string str : MemoryFilter::GetInstance().TITLE_HAS_PID_) {
127 vector<string> types;
128 StringUtils::GetInstance().StringSplit(str, "_", types);
129 if (types.size() == TYPE_SIZE) {
130 string title1 = types.at(0);
131 StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, title1);
132 line1.push_back(title1 + BLANK_);
133
134 string title2 = types.at(1);
135 StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, title2);
136 line2.push_back(title2 + BLANK_);
137 line3.push_back(unit + BLANK_);
138 line4.push_back(separator + SEPARATOR_);
139 }
140 }
141 result->push_back(line1);
142 result->push_back(line2);
143 result->push_back(line3);
144 result->push_back(line4);
145 }
146
UpdateResult(const int32_t & pid,const unique_ptr<ProcessMemoryDetail> & processMemoryDetail,unique_ptr<MemoryDetail> & nativeHeapDetail,StringMatrix result)147 void MemoryInfo::UpdateResult(const int32_t& pid, const unique_ptr<ProcessMemoryDetail>& processMemoryDetail,
148 unique_ptr<MemoryDetail>& nativeHeapDetail, StringMatrix result)
149 {
150 unique_ptr<MallHeapInfo> mallocHeapInfo = make_unique<MallHeapInfo>();
151 unique_ptr<GetHeapInfo> getHeapInfo = make_unique<GetHeapInfo>();
152 getHeapInfo->GetMallocHeapInfo(pid, mallocHeapInfo);
153 unique_ptr<MemoryDetail> anonPageDetail = make_unique<MemoryDetail>();
154 unique_ptr<MemoryDetail> filePageDetail = make_unique<MemoryDetail>();
155 vector<MemoryDetail> memoryDetails = processMemoryDetail->details;
156 map<string, unique_ptr<MemoryDetail>> allDetailMap;
157 for (const auto& memoryDetail : memoryDetails) {
158 MemoryClass memoryClass = memoryDetail.memoryClass;
159 if (static_cast<int>(memoryClass) < 0 || static_cast<size_t>(memoryClass) > MEMORY_CLASS_VEC.size()) {
160 DUMPER_HILOGE(MODULE_SERVICE, "memoryClass:%{public}d is not exist", memoryClass);
161 continue;
162 }
163 string memoryClassStr = MEMORY_CLASS_VEC[static_cast<int>(memoryClass)];
164 unique_ptr<MemoryDetail> tempDetail = make_unique<MemoryDetail>(memoryDetail);
165 if (memoryClassStr == "graph") {
166 GetGraphicsMemoryByDetail(tempDetail, result);
167 } else if (memoryClassStr == MemoryFilter::GetInstance().NATIVE_HEAP_LABEL) {
168 nativeHeapDetail = make_unique<MemoryDetail>(memoryDetail);
169 } else if (memoryClassStr == MEMINFO_OTHER) {
170 UpdatePageDetail(anonPageDetail, filePageDetail, tempDetail);
171 tempDetail = std::move(anonPageDetail);
172 memoryClassStr = MEMINFO_ANONPAGE_OTHER;
173 }
174 auto it = std::find(MEMORY_PRINT_ORDER_VEC.begin(), MEMORY_PRINT_ORDER_VEC.end(), memoryClassStr);
175 if (it!= MEMORY_PRINT_ORDER_VEC.end()) {
176 allDetailMap[memoryClassStr] = std::move(tempDetail);
177 }
178 }
179 for (const auto &classStr : MEMORY_PRINT_ORDER_VEC) {
180 auto it = allDetailMap.find(classStr);
181 if (it != allDetailMap.end()) {
182 SetDetailRet(classStr, it->second, mallocHeapInfo, result);
183 }
184 }
185 SetDetailRet(MEMINFO_FILEPAGE_OTHER, filePageDetail, mallocHeapInfo, result);
186 UpdateTotalDetail(processMemoryDetail, mallocHeapInfo, result);
187 }
188
UpdatePageDetail(std::unique_ptr<MemoryDetail> & anonPageDetail,std::unique_ptr<MemoryDetail> & filePageDetail,const std::unique_ptr<MemoryDetail> & tempDetail)189 void MemoryInfo::UpdatePageDetail(std::unique_ptr<MemoryDetail>& anonPageDetail,
190 std::unique_ptr<MemoryDetail>& filePageDetail,
191 const std::unique_ptr<MemoryDetail>& tempDetail)
192 {
193 if (!tempDetail) {
194 DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
195 return;
196 }
197 vector<MemoryItem> memoryItems = tempDetail->items;
198 for (const auto& memoryItem : memoryItems) {
199 int32_t iNode = memoryItem.iNode;
200 if (iNode == 0) {
201 anonPageDetail->totalPss += memoryItem.pss;
202 anonPageDetail->totalSharedClean += memoryItem.sharedClean;
203 anonPageDetail->totalSharedDirty += memoryItem.sharedDirty;
204 anonPageDetail->totalPrivateClean += memoryItem.privateClean;
205 anonPageDetail->totalPrivateDirty += memoryItem.privateDirty;
206 anonPageDetail->totalSwap += memoryItem.swap;
207 anonPageDetail->totalSwapPss += memoryItem.swapPss;
208 } else {
209 filePageDetail->totalPss += memoryItem.pss;
210 filePageDetail->totalSharedClean += memoryItem.sharedClean;
211 filePageDetail->totalSharedDirty += memoryItem.sharedDirty;
212 filePageDetail->totalPrivateClean += memoryItem.privateClean;
213 filePageDetail->totalPrivateDirty += memoryItem.privateDirty;
214 filePageDetail->totalSwap += memoryItem.swap;
215 filePageDetail->totalSwapPss += memoryItem.swapPss;
216 }
217 }
218 }
219
SetDetailRet(const std::string & memoryClassStr,const std::unique_ptr<MemoryDetail> & detail,const std::unique_ptr<MallHeapInfo> & heapInfo,StringMatrix result)220 void MemoryInfo::SetDetailRet(const std::string& memoryClassStr, const std::unique_ptr<MemoryDetail>& detail,
221 const std::unique_ptr<MallHeapInfo>& heapInfo, StringMatrix result)
222 {
223 if (!detail) {
224 DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
225 return;
226 }
227 vector<string> tempResult;
228 SetValueForRet(memoryClassStr, tempResult);
229 SetValueForRet(to_string(detail->totalPss), tempResult);
230 SetValueForRet(to_string(detail->totalSharedClean), tempResult);
231 SetValueForRet(to_string(detail->totalSharedDirty), tempResult);
232 SetValueForRet(to_string(detail->totalPrivateClean), tempResult);
233 SetValueForRet(to_string(detail->totalPrivateDirty), tempResult);
234 SetValueForRet(to_string(detail->totalSwap), tempResult);
235 SetValueForRet(to_string(detail->totalSwapPss), tempResult);
236 if (memoryClassStr == MemoryFilter::GetInstance().NATIVE_HEAP_LABEL) {
237 SetValueForRet(to_string(heapInfo->size), tempResult);
238 SetValueForRet(to_string(heapInfo->alloc), tempResult);
239 SetValueForRet(to_string(heapInfo->free), tempResult);
240 } else {
241 for (int i = 0; i < MALLOC_HEAP_TYPES; i++) {
242 SetValueForRet(ZERO, tempResult);
243 }
244 }
245 result->push_back(tempResult);
246 }
247
SetValueForRet(const std::string & value,std::vector<std::string> & tempResult)248 void MemoryInfo::SetValueForRet(const std::string& value, std::vector<std::string>& tempResult)
249 {
250 std::string tempStr = value;
251 StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, tempStr);
252 tempResult.push_back(tempStr + BLANK_);
253 }
254
UpdateTotalDetail(const std::unique_ptr<ProcessMemoryDetail> & detail,const std::unique_ptr<MallHeapInfo> & heapInfo,StringMatrix result)255 void MemoryInfo::UpdateTotalDetail(const std::unique_ptr<ProcessMemoryDetail>& detail,
256 const std::unique_ptr<MallHeapInfo>& heapInfo, StringMatrix result)
257 {
258 if (!detail) {
259 DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
260 return;
261 }
262 vector<string> lines;
263 vector<string> values;
264 uint64_t totalPrivateDirty = static_cast<uint64_t>(detail->totalPrivateDirty) + graphicsMemory_.gl +
265 graphicsMemory_.graph;
266 currentPss_ = detail->totalAllPss;
267 MemoryUtil::GetInstance().SetMemTotalValue(MEMINFO_TOTAL, lines, values);
268 MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalAllPss), lines, values);
269 MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSharedClean), lines, values);
270 MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSharedDirty), lines, values);
271 MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalPrivateClean), lines, values);
272 MemoryUtil::GetInstance().SetMemTotalValue(to_string(totalPrivateDirty), lines, values);
273 MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSwap), lines, values);
274 MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSwapPss), lines, values);
275 MemoryUtil::GetInstance().SetMemTotalValue(to_string(heapInfo->size), lines, values);
276 MemoryUtil::GetInstance().SetMemTotalValue(to_string(heapInfo->alloc), lines, values);
277 MemoryUtil::GetInstance().SetMemTotalValue(to_string(heapInfo->free), lines, values);
278
279 // delete the last separator
280 if (!lines.empty()) {
281 lines.pop_back();
282 string separator = "-";
283 StringUtils::GetInstance().SetWidth(LINE_WIDTH_, SEPARATOR_, false, separator);
284 lines.push_back(separator);
285 }
286 result->push_back(lines);
287 result->push_back(values);
288 }
289
CalculateStars(const std::vector<int> & pssValues,int currentPSS)290 int MemoryInfo::CalculateStars(const std::vector<int>& pssValues, int currentPSS)
291 {
292 if (pssValues.empty()) {
293 return MAX_STARS_NUM;
294 }
295 auto [min_it, max_it] = std::minmax_element(pssValues.begin(), pssValues.end());
296 int minPSS = *min_it;
297 int maxPSS = *max_it;
298 if (maxPSS == minPSS) {
299 return MAX_STARS_NUM;
300 }
301 double stdValue = static_cast<double>(currentPSS - minPSS) / (maxPSS - minPSS);
302 return static_cast<int>(stdValue * (MAX_STARS_NUM - ONE_STAR) + ONE_STAR);
303 }
304
WriteStdout(const std::string & s)305 void MemoryInfo::WriteStdout(const std::string& s)
306 {
307 write(rawParamFd_, s.c_str(), s.size());
308 }
309
ClearPreviousLines(int lineCount)310 void MemoryInfo::ClearPreviousLines(int lineCount)
311 {
312 for (int i = 0; i < lineCount; ++i) {
313 WriteStdout("\033[F");
314 WriteStdout("\033[2K");
315 }
316 }
317
GenerateLine(const std::vector<int> & pssValues,int index)318 std::string MemoryInfo::GenerateLine(const std::vector<int>& pssValues, int index)
319 {
320 DUMPER_HILOGI(MODULE_SERVICE, "pss:%{public}d", pssValues[index]);
321 int stars = CalculateStars(pssValues, pssValues[index]);
322 const int TOTAL_WIDTH = 26;
323 std::stringstream ss;
324 ss << std::string(stars, '*')
325 << std::string(TOTAL_WIDTH - stars, ' ')
326 << "times" << (index + 1) << ": PSS=" << pssValues[index] << "kB\n";
327 return ss.str();
328 }
329
GenerateTimestamps(const std::vector<int> & pssValues)330 std::string MemoryInfo::GenerateTimestamps(const std::vector<int>& pssValues)
331 {
332 std::string endTime;
333 DumpCommonUtils::GetDateAndTime(DumpCommonUtils::GetMilliseconds() / SECOND_TO_MILLISECONDS, endTime);
334 int timeIndex = static_cast<int>(pssValues.size());
335 int maxMem = *std::max_element(pssValues.begin(), pssValues.end());
336 int changePss = 0;
337 if (pssValues.size() > 1) {
338 changePss = pssValues[pssValues.size() - 1] - pssValues[0];
339 }
340
341 StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, startTime_);
342 StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, endTime);
343 string count = to_string(timeIndex);
344 StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, count);
345 string maxMemStr = to_string(maxMem) + "kB";
346 StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, maxMemStr);
347 string changePssStr = to_string(changePss) + "kB";
348 StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, changePssStr);
349 return "StartTime EndTime Count MaxMem Change\n" +
350 startTime_ + endTime + " " + count + " " + maxMemStr + " " + changePssStr + "\n";
351 }
352
CalculateMaxIdex(const std::vector<int> & pssValues,int * maxIndex)353 void MemoryInfo::CalculateMaxIdex(const std::vector<int>& pssValues, int *maxIndex)
354 {
355 const int minIndex = 5;
356 const int lastLines = 5;
357 for (int i = minIndex; i < static_cast<int>(pssValues.size()) - lastLines; ++i) {
358 if (pssValues[i] > pssValues[*maxIndex]) {
359 *maxIndex = i;
360 }
361 }
362 }
363
PrintMemoryInfo(const std::vector<int> & pssValues,int * prevLineCount)364 void MemoryInfo::PrintMemoryInfo(const std::vector<int>& pssValues, int* prevLineCount)
365 {
366 static int lastMaxIndex = -1;
367 static int numHeaderLines = 2;
368 const int minIndex = 5;
369 const int lastLines = 5;
370 const int thresholdLines = 6;
371 const size_t maxPssValues = 10;
372 int currentLineCount = 0;
373 std::string output;
374
375 output += GenerateTimestamps(pssValues);
376 currentLineCount += numHeaderLines;
377
378 if (pssValues.size() <= maxPssValues) {
379 currentLineCount += static_cast<int>(pssValues.size());
380 for (size_t i = 0; i < pssValues.size(); ++i) {
381 output += GenerateLine(pssValues, static_cast<int>(i));
382 }
383 } else {
384 int maxIndex = 0;
385 CalculateMaxIdex(pssValues, &maxIndex);
386 for (int i = 0; i < minIndex; ++i) {
387 output += GenerateLine(pssValues, i);
388 currentLineCount++;
389 }
390
391 if (maxIndex >= minIndex && maxIndex < static_cast<int>(pssValues.size()) - lastLines) {
392 if (maxIndex > minIndex) {
393 output += "...\n";
394 currentLineCount++;
395 }
396
397 output += GenerateLine(pssValues, maxIndex);
398 currentLineCount++;
399
400 if (maxIndex < static_cast<int>(pssValues.size()) - thresholdLines) {
401 output += "...\n";
402 currentLineCount++;
403 }
404
405 lastMaxIndex = maxIndex;
406 } else {
407 output += "...\n";
408 currentLineCount++;
409 }
410
411 for (int i = static_cast<int>(pssValues.size()) - lastLines; i < static_cast<int>(pssValues.size()); ++i) {
412 output += GenerateLine(pssValues, i);
413 currentLineCount++;
414 }
415 }
416
417 if (*prevLineCount > 0) {
418 ClearPreviousLines(*prevLineCount);
419 }
420
421 WriteStdout(output);
422 *prevLineCount = currentLineCount;
423 }
424
SetReceivedSigInt(bool isReceivedSigInt)425 void MemoryInfo::SetReceivedSigInt(bool isReceivedSigInt)
426 {
427 DUMPER_HILOGI(MODULE_SERVICE, "isReceivedSigInt: %{public}d", isReceivedSigInt);
428 g_isDumpMem = !isReceivedSigInt;
429 }
430
RedirectMemoryInfo(int timeIndex,StringMatrix result)431 void MemoryInfo::RedirectMemoryInfo(int timeIndex, StringMatrix result)
432 {
433 int redirectFd = DumpUtils::FdToWrite("/data/log/hidumper/record_mem.txt");
434 if (redirectFd <= -1) {
435 DUMPER_HILOGE(MODULE_COMMON, "write to record_mem.txt failed");
436 return;
437 }
438 string timeTitle = "\ntimes:" + to_string(timeIndex) + "\n";
439 write(redirectFd, timeTitle.c_str(), strlen(timeTitle.c_str()));
440 for (size_t i = 0; i < result->size(); i++) {
441 std::vector<std::string> line = result->at(i);
442 for (size_t j = 0; j < line.size(); j++) {
443 std::string str = line[j];
444 if ((j == (line.size() - 1)) && (str.find("\n") == std::string::npos)) {
445 str = str + "\n";
446 }
447 if (write(redirectFd, str.c_str(), strlen(str.c_str())) == -1) {
448 DUMPER_HILOGE(MODULE_COMMON, "write to rawParamFd failed, errno: %{public}d", errno);
449 }
450 }
451 }
452 close(redirectFd);
453 }
454
GetMemoryInfoByTimeInterval(int fd,const int32_t & pid,const int32_t & timeInterval)455 void MemoryInfo::GetMemoryInfoByTimeInterval(int fd, const int32_t &pid, const int32_t &timeInterval)
456 {
457 std::lock_guard<std::mutex> lock(timeIntervalMutex_);
458 rawParamFd_ = fd;
459 (void)dprintf(rawParamFd_, "%s\n\n", MEMORY_LINE.c_str());
460 DumpCommonUtils::GetDateAndTime(DumpCommonUtils::GetMilliseconds() / SECOND_TO_MILLISECONDS, startTime_);
461 DUMPER_HILOGI(MODULE_SERVICE, "GetMemoryInfoByTimeInterval timeInterval:%{public}d", timeInterval);
462 std::vector<int> pssValues;
463 int prevLineCount = 0;
464 while (g_isDumpMem) {
465 StringMatrix result = std::make_shared<std::vector<std::vector<std::string>>>();
466 GetMemoryInfoByPid(pid, result, false, false);
467 pssValues.push_back(static_cast<int>(currentPss_));
468 PrintMemoryInfo(pssValues, &prevLineCount);
469 RedirectMemoryInfo(static_cast<int>(pssValues.size()), result);
470 sleep(timeInterval);
471 }
472 g_isDumpMem = true;
473 DUMPER_HILOGI(MODULE_SERVICE, "GetMemoryInfoByTimeInterval timeInterval:%{public}d end", timeInterval);
474 }
475
GetMemoryInfoByPid(const int32_t & pid,StringMatrix result,bool showAshmem,bool showDmaBuf)476 bool MemoryInfo::GetMemoryInfoByPid(const int32_t &pid, StringMatrix result, bool showAshmem, bool showDmaBuf)
477 {
478 std::lock_guard<std::mutex> lock(mutex_);
479 InsertMemoryTitle(result);
480 GetResult(pid, result);
481 GetPurgByPid(pid, result);
482 GetDma(graphicsMemory_.graph, result);
483 GetDmaBuf(pid, result, showDmaBuf);
484 GetHiaiServerIon(pid, result);
485 GetAshmem(pid, result, showAshmem);
486 return true;
487 }
488
GetResult(const int32_t & pid,StringMatrix result)489 void MemoryInfo::GetResult(const int32_t& pid, StringMatrix result)
490 {
491 DUMPER_HILOGD(MODULE_SERVICE, "CollectProcessMemoryDetail pid:%{public}d start", pid);
492 std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create();
493 CollectResult<ProcessMemoryDetail> collectRet;
494 collectRet = collector->CollectProcessMemoryDetail(pid, GraphicMemOption::LOW_LATENCY);
495 if (collectRet.retCode != UCollect::UcError::SUCCESS) {
496 DUMPER_HILOGE(MODULE_SERVICE, "collect process memory error, ret:%{public}d", collectRet.retCode);
497 return;
498 }
499 unique_ptr<ProcessMemoryDetail> processMemoryDetail = make_unique<ProcessMemoryDetail>(collectRet.data);
500 if (!processMemoryDetail) {
501 DUMPER_HILOGE(MODULE_SERVICE, "processMemoryDetail is nullptr");
502 return;
503 }
504 DUMPER_HILOGD(MODULE_SERVICE, "CollectProcessMemoryDetail pid:%{public}d end", pid);
505 unique_ptr<MemoryDetail> nativeHeapDetail = {nullptr};
506 UpdateResult(pid, processMemoryDetail, nativeHeapDetail, result);
507 GetNativeHeap(nativeHeapDetail, result);
508 }
509
GetGraphicsMemoryByDetail(const std::unique_ptr<MemoryDetail> & detail,StringMatrix result)510 void MemoryInfo::GetGraphicsMemoryByDetail(const std::unique_ptr<MemoryDetail>& detail, StringMatrix result)
511 {
512 if (!detail) {
513 DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
514 return;
515 }
516 vector<MemoryItem> memoryItems = detail->items;
517 for (const auto& memoryItem : memoryItems) {
518 MemoryItemType memoryItemType = memoryItem.type;
519 auto info = GRAPHIC_MAP.find(memoryItemType);
520 if (info == GRAPHIC_MAP.end()) {
521 DUMPER_HILOGE(MODULE_SERVICE, "memoryItemType = %{public}d is not exist", memoryItemType);
522 continue;
523 }
524 string type = info->second;
525 if (type == MemoryFilter::GetInstance().GL_OUT_LABEL) {
526 graphicsMemory_.gl = memoryItem.pss;
527 } else if (type == MemoryFilter::GetInstance().GRAPH_OUT_LABEL) {
528 graphicsMemory_.graph = memoryItem.pss;
529 }
530 }
531 UpdateGraphicsMemoryRet(MemoryFilter::GetInstance().GL_OUT_LABEL, graphicsMemory_.gl, result);
532 UpdateGraphicsMemoryRet(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, graphicsMemory_.graph, result);
533 }
534
UpdateGraphicsMemoryRet(const string & title,const uint64_t & value,StringMatrix result)535 void MemoryInfo::UpdateGraphicsMemoryRet(const string& title, const uint64_t& value, StringMatrix result)
536 {
537 map<string, uint64_t> valueMap;
538 valueMap.insert(pair<string, uint64_t>(MEMINFO_PSS, value));
539 valueMap.insert(pair<string, uint64_t>(MEMINFO_PRIVATE_DIRTY, value));
540 vector<string> tempResult;
541 string tempTitle = title;
542 StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, tempTitle);
543 tempResult.push_back(tempTitle + BLANK_);
544 for (const auto &tag : MemoryFilter::GetInstance().VALUE_WITH_PID) {
545 auto it = valueMap.find(tag);
546 string value = ZERO;
547 if (it != valueMap.end()) {
548 value = to_string(it->second);
549 }
550 StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, value);
551 tempResult.push_back(value + BLANK_);
552 }
553 result->push_back(tempResult);
554 }
555
AddKbUnit(const uint64_t & value) const556 string MemoryInfo::AddKbUnit(const uint64_t &value) const
557 {
558 return to_string(value) + MemoryUtil::GetInstance().KB_UNIT_;
559 }
560
GetSmapsInfoNoPid(const int32_t & pid,GroupMap & result)561 bool MemoryInfo::GetSmapsInfoNoPid(const int32_t &pid, GroupMap &result)
562 {
563 GroupMap NativeMap;
564 unique_ptr<ParseSmapsInfo> parseSmapsInfo = make_unique<ParseSmapsInfo>();
565 return parseSmapsInfo->GetInfo(MemoryFilter::NOT_SPECIFIED_PID, pid, NativeMap, result);
566 }
567
GetMeminfo(ValueMap & result)568 bool MemoryInfo::GetMeminfo(ValueMap &result)
569 {
570 unique_ptr<ParseMeminfo> parseMeminfo = make_unique<ParseMeminfo>();
571 return parseMeminfo->GetMeminfo(result);
572 }
573
GetHardWareUsage(StringMatrix result)574 bool MemoryInfo::GetHardWareUsage(StringMatrix result)
575 {
576 uint64_t value;
577 unique_ptr<GetHardwareInfo> getHardwareInfo = make_unique<GetHardwareInfo>();
578 if (getHardwareInfo->GetHardwareUsage(value)) {
579 string title = "Hardware Usage:";
580 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
581 SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
582 return true;
583 }
584 return false;
585 }
586
GetCMAUsage(StringMatrix result)587 bool MemoryInfo::GetCMAUsage(StringMatrix result)
588 {
589 uint64_t value = 0;
590 unique_ptr<GetCMAInfo> getCMAInfo = make_unique<GetCMAInfo>();
591 bool success = getCMAInfo->GetUsed(value);
592 if (success) {
593 string title = "CMA Usage:";
594 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
595 SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
596 }
597 return success;
598 }
599
GetKernelUsage(const ValueMap & infos,StringMatrix result)600 bool MemoryInfo::GetKernelUsage(const ValueMap &infos, StringMatrix result)
601 {
602 uint64_t value = 0;
603 unique_ptr<GetKernelInfo> getGetKernelInfo = make_unique<GetKernelInfo>();
604 bool success = getGetKernelInfo->GetKernel(infos, value);
605 if (success) {
606 string title = "Kernel Usage:";
607 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
608 SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
609 }
610 return success;
611 }
612
GetProcesses(const GroupMap & infos,StringMatrix result)613 void MemoryInfo::GetProcesses(const GroupMap &infos, StringMatrix result)
614 {
615 uint64_t value = 0;
616
617 unique_ptr<GetProcessInfo> getProcessInfo = make_unique<GetProcessInfo>();
618 value = getProcessInfo->GetProcess(infos);
619
620 string title = "Processes Usage:";
621 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
622 SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
623 }
624
GetPssTotal(const GroupMap & infos,StringMatrix result)625 void MemoryInfo::GetPssTotal(const GroupMap &infos, StringMatrix result)
626 {
627 SaveStringToFd(rawParamFd_, "Total Pss by Category:\n");
628 vector<pair<string, uint64_t>> filePage;
629 vector<pair<string, uint64_t>> anonPage;
630 for (const auto &info : infos) {
631 vector<string> pageTag;
632 StringUtils::GetInstance().StringSplit(info.first, "#", pageTag);
633 if (pageTag.size() < PAGETAG_MIN_LEN) {
634 DUMPER_HILOGE(MODULE_COMMON, "Infos are invalid, info.first: %{public}s", info.first.c_str());
635 continue;
636 }
637 string group = pageTag[1];
638 auto &valueMap = info.second;
639 uint64_t pssValue = 0;
640 for (const auto &str : MemoryFilter::GetInstance().CALC_PSS_TOTAL_) {
641 auto it = valueMap.find(str);
642 if (it != valueMap.end()) {
643 pssValue += it->second;
644 }
645 }
646
647 if (pageTag[0] == MemoryFilter::GetInstance().FILE_PAGE_TAG) {
648 filePage.push_back(make_pair(group, pssValue));
649 } else {
650 anonPage.push_back(make_pair(group, pssValue));
651 }
652 }
653 PairToStringMatrix(MemoryFilter::GetInstance().FILE_PAGE_TAG, filePage, result);
654 PairToStringMatrix(MemoryFilter::GetInstance().ANON_PAGE_TAG, anonPage, result);
655
656 vector<pair<string, uint64_t>> gpuValue;
657 gpuValue.push_back(make_pair(MemoryFilter::GetInstance().GL_OUT_LABEL, totalGL_));
658 PairToStringMatrix(MemoryFilter::GetInstance().GPU_TAG, gpuValue, result);
659
660 vector<pair<string, uint64_t>> graphValue;
661 graphValue.push_back(make_pair(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, totalGraph_));
662 PairToStringMatrix(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, graphValue, result);
663
664 vector<pair<string, uint64_t>> dmaValue;
665 dmaValue.push_back(make_pair(MemoryFilter::GetInstance().DMA_OUT_LABEL, totalDma_));
666 PairToStringMatrix(MemoryFilter::GetInstance().DMA_TAG, dmaValue, result);
667 }
668
PairToStringMatrix(const string & titleStr,vector<pair<string,uint64_t>> & vec,StringMatrix result)669 void MemoryInfo::PairToStringMatrix(const string &titleStr, vector<pair<string, uint64_t>> &vec, StringMatrix result)
670 {
671 uint64_t totalPss = accumulate(vec.begin(), vec.end(), (uint64_t)0, [] (uint64_t a, pair<string, uint64_t> &b) {
672 return a + b.second;
673 });
674 SaveStringToFd(rawParamFd_, titleStr + "(" + AddKbUnit(totalPss) + "):\n");
675
676 std::sort(vec.begin(), vec.end(),
677 [] (pair<string, uint64_t> &left, pair<string, uint64_t> &right) {
678 return right.second < left.second;
679 });
680 for (const auto &pair : vec) {
681 string pssStr = AddKbUnit(pair.second);
682 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, pssStr);
683 SaveStringToFd(rawParamFd_, pssStr + " : " + pair.first + "\n");
684 }
685 }
686
GetRamUsage(const GroupMap & smapsinfos,const ValueMap & meminfo,StringMatrix result)687 void MemoryInfo::GetRamUsage(const GroupMap &smapsinfos, const ValueMap &meminfo, StringMatrix result)
688 {
689 unique_ptr<GetRamInfo> getRamInfo = make_unique<GetRamInfo>();
690 GetRamInfo::Ram ram = getRamInfo->GetRam(smapsinfos, meminfo);
691
692 string totalTitle = "Total RAM:";
693 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalTitle);
694 SaveStringToFd(rawParamFd_, totalTitle + AddKbUnit(ram.total) + "\n");
695
696 string freeTitle = "Free RAM:";
697 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, freeTitle);
698 SaveStringToFd(rawParamFd_, freeTitle + AddKbUnit(ram.free) +
699 " (" + to_string(ram.cachedInfo) + " cached + " + to_string(ram.freeInfo) + " free)\n");
700
701 string usedTitle = "Used RAM:";
702 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, usedTitle);
703 SaveStringToFd(rawParamFd_, usedTitle + AddKbUnit(ram.used) +
704 " (" + to_string(ram.totalPss) + " total pss + " + to_string(ram.kernelUsed) + " kernel)\n");
705
706 string lostTitle = "Lost RAM:";
707 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, lostTitle);
708 SaveStringToFd(rawParamFd_, lostTitle + to_string(ram.lost) + MemoryUtil::GetInstance().KB_UNIT_ + "\n");
709 }
710
GetPurgTotal(const ValueMap & meminfo,StringMatrix result)711 void MemoryInfo::GetPurgTotal(const ValueMap &meminfo, StringMatrix result)
712 {
713 SaveStringToFd(rawParamFd_, "Total Purgeable:\n");
714
715 uint64_t purgSumTotal = 0;
716 uint64_t purgPinTotal = 0;
717 auto purgSumActive = meminfo.find(MemoryFilter::GetInstance().PURG_SUM[0]);
718 auto purgSumInactive = meminfo.find(MemoryFilter::GetInstance().PURG_SUM[1]);
719 auto purgPinPined = meminfo.find(MemoryFilter::GetInstance().PURG_PIN[0]);
720 if (purgSumActive == meminfo.end() || purgSumInactive == meminfo.end() || purgPinPined == meminfo.end()) {
721 DUMPER_HILOGE(MODULE_SERVICE, "fail to get purg info \n");
722 } else {
723 purgSumTotal = purgSumActive->second + purgSumInactive->second;
724 purgPinTotal = purgPinPined->second;
725 }
726
727 string totalPurgSumTitle = "Total PurgSum:";
728 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalPurgSumTitle);
729 SaveStringToFd(rawParamFd_, totalPurgSumTitle + AddKbUnit(purgSumTotal) + "\n");
730
731 string totalPurgPinTitle = "Total PurgPin:";
732 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalPurgPinTitle);
733 SaveStringToFd(rawParamFd_, totalPurgPinTitle + AddKbUnit(purgPinTotal) + "\n");
734 }
735
GetPurgByPid(const int32_t & pid,StringMatrix result)736 void MemoryInfo::GetPurgByPid(const int32_t &pid, StringMatrix result)
737 {
738 AddBlankLine(result);
739 vector<string> title;
740 title.push_back("Purgeable:");
741 result->push_back(title);
742
743 vector<string> purgSum;
744 string purgSumTitle = MemoryFilter::GetInstance().PURGSUM_OUT_LABEL + ":";
745 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, purgSumTitle);
746 purgSum.push_back(purgSumTitle);
747 purgSum.push_back(AddKbUnit(GetProcValue(pid, MemoryFilter::GetInstance().PURGSUM_OUT_LABEL)));
748 result->push_back(purgSum);
749
750 vector<string> purgPin;
751 string purgPinTitle = MemoryFilter::GetInstance().PURGPIN_OUT_LABEL + ":";
752 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, purgPinTitle);
753 purgPin.push_back(purgPinTitle);
754 purgPin.push_back(AddKbUnit(GetProcValue(pid, MemoryFilter::GetInstance().PURGPIN_OUT_LABEL)));
755 result->push_back(purgPin);
756 }
757
GetNativeHeap(const std::unique_ptr<MemoryDetail> & detail,StringMatrix result)758 void MemoryInfo::GetNativeHeap(const std::unique_ptr<MemoryDetail>& detail, StringMatrix result)
759 {
760 if (!detail) {
761 DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
762 return;
763 }
764 AddBlankLine(result);
765 vector<string> title;
766 title.push_back(MemoryFilter::GetInstance().NATIVE_HEAP_LABEL + ":");
767 result->push_back(title);
768
769 vector<MemoryItem> memoryItems = detail->items;
770 for (const auto& memoryItem : memoryItems) {
771 MemoryItemType memoryItemType = memoryItem.type;
772 auto info = NATIVE_HEAP_MAP.find(memoryItemType);
773 if (info == NATIVE_HEAP_MAP.end()) {
774 DUMPER_HILOGE(MODULE_SERVICE, "memoryItemType = %{public}d is not exist", memoryItemType);
775 continue;
776 }
777 string type = info->second;
778 auto it = memoryItemMap_.find(type);
779 if (it == memoryItemMap_.end()) {
780 memoryItemMap_.insert(pair<string, MemoryItem>(type, memoryItem));
781 } else {
782 it->second.pss += memoryItem.pss;
783 it->second.sharedClean += memoryItem.sharedClean;
784 it->second.sharedDirty += memoryItem.sharedDirty;
785 it->second.privateClean += memoryItem.privateClean;
786 it->second.privateDirty += memoryItem.privateDirty;
787 it->second.swap += memoryItem.swap;
788 it->second.swapPss += memoryItem.swapPss;
789 }
790 }
791 for (const auto& type: NATIVE_HEAP_TAG) {
792 auto it = memoryItemMap_.find(type);
793 if (it == memoryItemMap_.end()) {
794 continue;
795 }
796 string heapTitle = it->first;
797 unique_ptr<MemoryItem> item = make_unique<MemoryItem>(it->second);
798 SetNativeDetailRet(type, item, result);
799 }
800 }
801
SetNativeDetailRet(const std::string & nativeClassStr,const std::unique_ptr<MemoryItem> & item,StringMatrix result)802 void MemoryInfo::SetNativeDetailRet(const std::string& nativeClassStr, const std::unique_ptr<MemoryItem>& item,
803 StringMatrix result)
804 {
805 vector<string> heap;
806 string heapTitle = nativeClassStr + ":";
807 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, heapTitle);
808 heap.push_back(heapTitle);
809 SetValueForRet(to_string(item->pss), heap);
810 SetValueForRet(to_string(item->sharedClean), heap);
811 SetValueForRet(to_string(item->sharedDirty), heap);
812 SetValueForRet(to_string(item->privateClean), heap);
813 SetValueForRet(to_string(item->privateDirty), heap);
814 SetValueForRet(to_string(item->swap), heap);
815 SetValueForRet(to_string(item->swapPss), heap);
816 for (int i = 0; i < MALLOC_HEAP_TYPES; i++) {
817 SetValueForRet(ZERO, heap);
818 }
819 result->push_back(heap);
820 }
821
GetDma(const uint64_t & dmaValue,StringMatrix result)822 void MemoryInfo::GetDma(const uint64_t& dmaValue, StringMatrix result)
823 {
824 AddBlankLine(result);
825 vector<string> title;
826 title.push_back(MemoryFilter::GetInstance().DMA_TAG + ":");
827 result->push_back(title);
828
829 vector<string> dma;
830 string dmaTitle = MemoryFilter::GetInstance().DMA_OUT_LABEL + ":";
831 StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, dmaTitle);
832 dma.push_back(dmaTitle);
833 dma.push_back(to_string(dmaValue) + MemoryUtil::GetInstance().KB_UNIT_);
834 result->push_back(dma);
835 }
836
GetHiaiServerIon(const int32_t & pid,StringMatrix result)837 void MemoryInfo::GetHiaiServerIon(const int32_t &pid, StringMatrix result)
838 {
839 if (GetProcName(pid) != "hiaiserver") {
840 return;
841 }
842 void *handle = dlopen(LIB.c_str(), RTLD_LAZY);
843 if (handle == nullptr) {
844 DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s.", LIB.c_str());
845 return;
846 }
847 HiaiFunc pfn = reinterpret_cast<HiaiFunc>(dlsym(handle, HIAI_MEM_INFO_FN));
848 if (pfn == nullptr) {
849 DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym %{public}s.", HIAI_MEM_INFO_FN);
850 dlclose(handle);
851 return;
852 }
853 MemInfoData::HiaiUserAllocatedMemInfo memInfos[HIAI_MAX_QUERIED_USER_MEMINFO_LIMIT] = {};
854
855 int realSize = 0;
856 pfn(memInfos, HIAI_MAX_QUERIED_USER_MEMINFO_LIMIT, &realSize);
857 if (realSize > 0) {
858 AddBlankLine(result);
859 vector<string> vecIon;
860 vecIon.push_back("HIAIServer ION:\n");
861 for (int i = 0; i < realSize; i++) {
862 vecIon.push_back(GetProcName(memInfos[i].pid) + "(" + to_string(memInfos[i].pid) + "):" +
863 to_string(memInfos[i].size / BYTE_PER_KB) + " kB\n");
864 }
865 result->push_back(vecIon);
866 }
867 dlclose(handle);
868 }
869
GetAshmem(const int32_t & pid,StringMatrix result,bool showAshmem)870 void MemoryInfo::GetAshmem(const int32_t &pid, StringMatrix result, bool showAshmem)
871 {
872 std::pair<int, std::vector<std::string>> ashmemInfo;
873 unique_ptr<ParseAshmemInfo> parseAshmeminfo = make_unique<ParseAshmemInfo>();
874 if (!parseAshmeminfo->GetAshmemInfo(pid, ashmemInfo)) {
875 DUMPER_HILOGE(MODULE_SERVICE, "GetAshmemInfo error");
876 return;
877 }
878 if (ashmemInfo.second.size() == 0) {
879 DUMPER_HILOGE(MODULE_SERVICE, "no detail ashmem info.");
880 return;
881 }
882 AddBlankLine(result);
883 vector<string> title;
884 title.push_back("Ashmem:");
885 result->push_back(title);
886 vector<string> totalAshmemVec;
887 totalAshmemVec.push_back("Total Ashmem:" + to_string(ashmemInfo.first) + MemoryUtil::GetInstance().KB_UNIT_);
888 result->push_back(totalAshmemVec);
889 if (showAshmem) {
890 for (auto detailInfo : ashmemInfo.second) {
891 vector<string> tempResult;
892 tempResult.push_back(detailInfo);
893 result->push_back(tempResult);
894 }
895 }
896 }
897
GetDmaBuf(const int32_t & pid,StringMatrix result,bool showDmaBuf)898 void MemoryInfo::GetDmaBuf(const int32_t &pid, StringMatrix result, bool showDmaBuf)
899 {
900 if (!showDmaBuf) {
901 DUMPER_HILOGD(MODULE_SERVICE, "showDmaBuf is false, skip GetDmaBuf");
902 return;
903 }
904 int32_t uid = GetProcUid(pid);
905 if (uid < APP_UID) {
906 DUMPER_HILOGD(MODULE_SERVICE, "Uid Verification failed for uid: %{public}d", uid);
907 return;
908 }
909 std::vector<std::string> dmabufInfo;
910 std::vector<std::string> titles;
911 unordered_map<std::string, int> headerMap;
912 vector<int> columnWidths;
913 unique_ptr<ParseDmaBufInfo> parseDmaBufInfo = make_unique<ParseDmaBufInfo>();
914 if (!parseDmaBufInfo->GetDmaBufInfo(pid, dmabufInfo, headerMap, columnWidths, titles)) {
915 DUMPER_HILOGE(MODULE_SERVICE, "GetDmaBufInfo error");
916 return;
917 }
918 const std::unordered_set<std::string> exTitles = { "can_reclaim", "is_reclaim" };
919 for (const auto& dmabuf : dmabufInfo) {
920 std::istringstream ss(dmabuf);
921 std::ostringstream oss;
922 for (const auto& title : titles) {
923 std::string value;
924 if (!(ss >> value)) {
925 value = "NULL";
926 }
927 if (exTitles.find(title) != exTitles.end()) {
928 continue;
929 }
930 int width = columnWidths[headerMap[title]];
931 oss << std::left << std::setw(width + LINE_SPACING) << value;
932 }
933 vector<string> tempResult;
934 tempResult.push_back(oss.str());
935 result->push_back(tempResult);
936 }
937 }
938
GetRamCategory(const GroupMap & smapsInfos,const ValueMap & meminfos,StringMatrix result)939 void MemoryInfo::GetRamCategory(const GroupMap &smapsInfos, const ValueMap &meminfos, StringMatrix result)
940 {
941 SaveStringToFd(rawParamFd_, "Total RAM by Category:\n");
942
943 bool hardWareSuccess = GetHardWareUsage(result);
944 if (!hardWareSuccess) {
945 DUMPER_HILOGE(MODULE_SERVICE, "Get hardWare usage fail.\n");
946 }
947
948 bool cmaSuccess = GetCMAUsage(result);
949 if (!cmaSuccess) {
950 DUMPER_HILOGE(MODULE_SERVICE, "Get CMA fail.\n");
951 }
952
953 bool kernelSuccess = GetKernelUsage(meminfos, result);
954 if (!kernelSuccess) {
955 DUMPER_HILOGE(MODULE_SERVICE, "Get kernel usage fail.\n");
956 }
957
958 GetProcesses(smapsInfos, result);
959 }
960
AddBlankLine(StringMatrix result)961 void MemoryInfo::AddBlankLine(StringMatrix result)
962 {
963 vector<string> blank;
964 blank.push_back("\n");
965 result->push_back(blank);
966 }
967
GetProcName(const int32_t & pid)968 string MemoryInfo::GetProcName(const int32_t &pid)
969 {
970 string procName = UNKNOWN_PROCESS;
971 DumpCommonUtils::GetProcessNameByPid(pid, procName);
972 if (procName == UNKNOWN_PROCESS) {
973 string path = "/proc/" + to_string(pid) + "/status";
974 procName = FileUtils::GetInstance().GetProcValue(pid, path, "Name");
975 }
976 return procName;
977 }
978
GetProcUid(const int32_t & pid)979 int32_t MemoryInfo::GetProcUid(const int32_t &pid)
980 {
981 string path = "/proc/" + to_string(pid) + "/status";
982 string procUid = FileUtils::GetInstance().GetProcValue(pid, path, "Uid");
983 if (procUid == UNKNOWN_PROCESS) {
984 DUMPER_HILOGE(MODULE_SERVICE, "GetProcUid failed");
985 return -1;
986 }
987 istringstream uid_stream(procUid);
988 string value;
989 uid_stream >> value;
990 int uid = -1;
991 if (!StrToInt(value, uid)) {
992 DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed, value: %{public}s", value.c_str());
993 return -1;
994 }
995 return static_cast<int32_t>(uid);
996 }
997
GetProcValue(const int32_t & pid,const string & key)998 uint64_t MemoryInfo::GetProcValue(const int32_t &pid, const string& key)
999 {
1000 string path = "/proc/" + to_string(pid) + "/status";
1001 std::string value = FileUtils::GetInstance().GetProcValue(pid, path, key);
1002 if (value == UNKNOWN_PROCESS) {
1003 DUMPER_HILOGE(MODULE_SERVICE, "GetProcStatusValue failed");
1004 return 0;
1005 }
1006 int number = 0;
1007 value = value.substr(0, value.size() - 3); // 3: ' kB'
1008 if (value.find_last_of(' ') != std::string::npos) {
1009 value = value.substr(value.find_last_of(' ') + 1);
1010 }
1011 if (!StrToInt(value, number)) {
1012 DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed, value: %{public}s", value.c_str());
1013 return 0;
1014 }
1015 return static_cast<uint64_t>(number);
1016 }
1017
1018 #ifdef HIDUMPER_MEMMGR_ENABLE
GetProcessAdjLabel(const int32_t pid)1019 string MemoryInfo::GetProcessAdjLabel(const int32_t pid)
1020 {
1021 string adjLabel = Memory::RECLAIM_PRIORITY_UNKNOWN_DESC;
1022 string fillPath = "/proc/" + to_string(pid) + "/oom_score_adj";
1023 if (!DumpUtils::PathIsValid(fillPath)) {
1024 DUMPER_HILOGE(MODULE_COMMON, "GetProcessAdjLabel leave|false, PathIsValid");
1025 return adjLabel;
1026 }
1027 auto fp = fopen(fillPath.c_str(), "rb");
1028 if (fp == nullptr) {
1029 DUMPER_HILOGE(MODULE_COMMON, "Open oom_score_adj failed.");
1030 return adjLabel;
1031 }
1032 constexpr int bufSize = 128; // 128: buf size
1033 char buf[bufSize] = {0};
1034 size_t readSum = fread(buf, 1, bufSize, fp);
1035 (void)fclose(fp);
1036 fp = nullptr;
1037 if (readSum < 1) {
1038 DUMPER_HILOGE(MODULE_COMMON, "Read oom_score_adj failed.");
1039 return adjLabel;
1040 }
1041 int value = Memory::RECLAIM_PRIORITY_UNKNOWN;
1042 std::string label(buf);
1043 if (label.empty()) {
1044 DUMPER_HILOGE(MODULE_COMMON, "label is empty.");
1045 return adjLabel;
1046 }
1047 if (!StrToInt(label.substr(0, label.size() - 1), value)) {
1048 DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed.");
1049 return adjLabel;
1050 }
1051 adjLabel = Memory::GetReclaimPriorityString(value);
1052 return adjLabel;
1053 }
1054 #endif
1055
GetScoreAdj(const int32_t pid)1056 int MemoryInfo::GetScoreAdj(const int32_t pid)
1057 {
1058 string filePath = "/proc/" + to_string(pid) + "/oom_score_adj";
1059 if (!DumpUtils::PathIsValid(filePath)) {
1060 DUMPER_HILOGE(MODULE_COMMON, "GetScoreAdj leave|false, PathIsValid");
1061 return -1;
1062 }
1063 std::string content = "-1";
1064 OHOS::LoadStringFromFile(filePath, content);
1065 int value = Memory::RECLAIM_PRIORITY_UNKNOWN;
1066 if (!StrToInt(content.substr(0, content.size() - 1), value)) {
1067 DUMPER_HILOGE(MODULE_COMMON, "GetScoreAdj|StrToInt failed.");
1068 return -1;
1069 }
1070 return value;
1071 }
1072
GetPids()1073 bool MemoryInfo::GetPids()
1074 {
1075 bool success = DumpCommonUtils::GetUserPids(pids_);
1076 if (!success) {
1077 DUMPER_HILOGE(MODULE_SERVICE, "GetPids error");
1078 }
1079 return success;
1080 }
1081
GetVss(const int32_t & pid)1082 uint64_t MemoryInfo::GetVss(const int32_t &pid)
1083 {
1084 string path = "/proc/" + to_string(pid) + "/statm";
1085 uint64_t res = 0;
1086 bool ret = FileUtils::GetInstance().LoadStringFromProcCb(path, true, true, [&](const string& line) -> void {
1087 if (!line.empty()) {
1088 uint64_t tempValue = 0;
1089 int retScanf = sscanf_s(line.c_str(), "%llu^*", &tempValue);
1090 if (retScanf != -1) {
1091 res = tempValue * VSS_BIT;
1092 } else {
1093 DUMPER_HILOGE(MODULE_SERVICE, "GetVss error! pid = %{public}d", pid);
1094 }
1095 }
1096 });
1097 if (!ret) {
1098 return 0;
1099 }
1100 return res;
1101 }
1102
GetGraphicsMemory(int32_t pid,MemInfoData::GraphicsMemory & graphicsMemory,GraphicType graphicType)1103 bool MemoryInfo::GetGraphicsMemory(int32_t pid, MemInfoData::GraphicsMemory &graphicsMemory, GraphicType graphicType)
1104 {
1105 DUMPER_HILOGD(MODULE_SERVICE, "GetGraphicUsage start, pid:%{public}d", pid);
1106 std::shared_ptr<UCollectUtil::GraphicMemoryCollector> collector = UCollectUtil::GraphicMemoryCollector::Create();
1107 CollectResult<int32_t> data;
1108 data = collector->GetGraphicUsage(pid, graphicType, true);
1109 if (data.retCode != UCollect::UcError::SUCCESS) {
1110 DUMPER_HILOGE(MODULE_SERVICE, "collect progress GL or Graph error, ret:%{public}d", data.retCode);
1111 return false;
1112 }
1113 DUMPER_HILOGD(MODULE_SERVICE, "GetGraphicUsage end, pid:%{public}d", pid);
1114 if (graphicType == GraphicType::GL) {
1115 graphicsMemory.gl = static_cast<uint64_t>(data.data);
1116 } else if (graphicType == GraphicType::GRAPH) {
1117 graphicsMemory.graph = static_cast<uint64_t>(data.data);
1118 } else {
1119 DUMPER_HILOGE(MODULE_SERVICE, "graphic type is not support.");
1120 return false;
1121 }
1122 return true;
1123 }
1124
GetMemByProcessPid(const int32_t & pid,MemInfoData::MemUsage & usage)1125 bool MemoryInfo::GetMemByProcessPid(const int32_t &pid, MemInfoData::MemUsage &usage)
1126 {
1127 bool success = false;
1128 MemInfoData::MemInfo memInfo;
1129 unique_ptr<ParseSmapsRollupInfo> getSmapsRollup = make_unique<ParseSmapsRollupInfo>();
1130 if (getSmapsRollup->GetMemInfo(pid, memInfo)) {
1131 if (!dumpPrune_) {
1132 usage.vss = GetVss(pid);
1133 usage.uss = memInfo.privateClean + memInfo.privateDirty;
1134 usage.rss = memInfo.rss;
1135 }
1136 usage.pss = memInfo.pss;
1137 usage.swapPss = memInfo.swapPss;
1138 usage.name = GetProcName(pid);
1139 usage.pid = pid;
1140 #ifdef HIDUMPER_MEMMGR_ENABLE
1141 usage.adjLabel = GetProcessAdjLabel(pid);
1142 #endif
1143 success = true;
1144 }
1145
1146 MemInfoData::GraphicsMemory graphicsMemory;
1147 MemoryUtil::GetInstance().InitGraphicsMemory(graphicsMemory);
1148 if (GetGraphicsMemory(pid, graphicsMemory, GraphicType::GL)) {
1149 usage.gl = graphicsMemory.gl;
1150 if (!dumpPrune_) {
1151 usage.uss = usage.uss + graphicsMemory.gl;
1152 usage.rss = usage.rss + graphicsMemory.gl;
1153 }
1154 usage.pss = usage.pss + graphicsMemory.gl;
1155 }
1156 if (!dumpPrune_) {
1157 if (GetGraphicsMemory(pid, graphicsMemory, GraphicType::GRAPH)) {
1158 usage.graph = graphicsMemory.graph;
1159 usage.dma = graphicsMemory.graph;
1160 usage.uss = usage.uss + graphicsMemory.graph;
1161 usage.pss = usage.pss + graphicsMemory.graph;
1162 usage.rss = usage.rss + graphicsMemory.graph;
1163 DUMPER_HILOGD(MODULE_SERVICE, "uss:%{public}d pss:%{public}d rss:%{public}d gl:%{public}d graph:%{public}d",
1164 static_cast<int>(usage.uss),
1165 static_cast<int>(usage.pss),
1166 static_cast<int>(usage.rss),
1167 static_cast<int>(graphicsMemory.gl),
1168 static_cast<int>(graphicsMemory.graph));
1169 }
1170 }
1171 return success;
1172 }
1173
MemUsageToMatrix(const MemInfoData::MemUsage & memUsage,StringMatrix result)1174 void MemoryInfo::MemUsageToMatrix(const MemInfoData::MemUsage &memUsage, StringMatrix result)
1175 {
1176 string pid = to_string(memUsage.pid);
1177 StringUtils::GetInstance().SetWidth(PID_WIDTH_, BLANK_, true, pid);
1178
1179 uint64_t pss = memUsage.pss + memUsage.swapPss;
1180 string totalPss = to_string(pss) + "(" + to_string(memUsage.swapPss) + " in SwapPss) kB";
1181 StringUtils::GetInstance().SetWidth(PSS_WIDTH_, BLANK_, false, totalPss);
1182
1183 uint64_t gl = memUsage.gl;
1184 string unMappedGL = AddKbUnit(gl);
1185 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGL);
1186
1187 string name = " " + memUsage.name;
1188 StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, name);
1189
1190 if (!dumpPrune_) {
1191 uint64_t vss = memUsage.vss;
1192 string totalVss = AddKbUnit(vss);
1193 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalVss);
1194
1195 uint64_t rss = memUsage.rss;
1196 string totalRss = AddKbUnit(rss);
1197 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalRss);
1198
1199 uint64_t uss = memUsage.uss;
1200 string totalUss = AddKbUnit(uss);
1201 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalUss);
1202
1203 uint64_t graph = memUsage.graph;
1204 string unMappedGraph = AddKbUnit(graph);
1205 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGraph);
1206
1207 uint64_t dma = memUsage.dma;
1208 string unMappedDma = AddKbUnit(dma);
1209 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedDma);
1210
1211 uint64_t purgSum = memUsage.purgSum;
1212 string unMappedPurgSum = AddKbUnit(purgSum);
1213 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgSum);
1214
1215 uint64_t purgPin = memUsage.purgPin;
1216 string unMappedPurgPin = AddKbUnit(purgPin);
1217 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgPin);
1218
1219 (void)dprintf(rawParamFd_, "%s %s %s %s %s %s %s %s %s %s %s\n", pid.c_str(),
1220 totalPss.c_str(), totalVss.c_str(), totalRss.c_str(), totalUss.c_str(),
1221 unMappedGL.c_str(), unMappedGraph.c_str(), unMappedDma.c_str(), unMappedPurgSum.c_str(),
1222 unMappedPurgPin.c_str(), name.c_str());
1223 } else {
1224 int scoreAdj = GetScoreAdj(memUsage.pid);
1225 string scoreAdjStr = to_string(scoreAdj);
1226 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, scoreAdjStr);
1227
1228 (void)dprintf(rawParamFd_, "%s %s %s %s %s\n", pid.c_str(),
1229 totalPss.c_str(), unMappedGL.c_str(), scoreAdjStr.c_str(), name.c_str());
1230 }
1231 }
1232
AddMemByProcessTitle(StringMatrix result,string sortType)1233 void MemoryInfo::AddMemByProcessTitle(StringMatrix result, string sortType)
1234 {
1235 string processTitle = "Total Memory Usage by " + sortType + ":";
1236 (void)dprintf(rawParamFd_, "%s\n", processTitle.c_str());
1237
1238 string pid = "PID";
1239 StringUtils::GetInstance().SetWidth(PID_WIDTH_, BLANK_, true, pid);
1240
1241 string totalPss = "Total Pss(xxx in SwapPss)";
1242 StringUtils::GetInstance().SetWidth(PSS_WIDTH_, BLANK_, false, totalPss);
1243
1244 string unMappedGL = MemoryFilter::GetInstance().GL_OUT_LABEL;
1245 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGL);
1246
1247 string name = " Name";
1248 StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, name);
1249
1250 if (!dumpPrune_) {
1251 string totalVss = "Total Vss";
1252 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalVss);
1253
1254 string totalRss = "Total Rss";
1255 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalRss);
1256
1257 string totalUss = "Total Uss";
1258 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalUss);
1259
1260 string unMappedGraph = MemoryFilter::GetInstance().GRAPH_OUT_LABEL;
1261 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGraph);
1262
1263 string unMappedDma = MemoryFilter::GetInstance().DMA_OUT_LABEL;
1264 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedDma);
1265
1266 string unMappedPurgSum = MemoryFilter::GetInstance().PURGSUM_OUT_LABEL;
1267 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgSum);
1268
1269 string unMappedPurgPin = MemoryFilter::GetInstance().PURGPIN_OUT_LABEL;
1270 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgPin);
1271
1272 (void)dprintf(rawParamFd_, "%s %s %s %s %s %s %s %s %s %s %s\n", pid.c_str(),
1273 totalPss.c_str(), totalVss.c_str(), totalRss.c_str(), totalUss.c_str(),
1274 unMappedGL.c_str(), unMappedGraph.c_str(), unMappedDma.c_str(), unMappedPurgSum.c_str(),
1275 unMappedPurgPin.c_str(), name.c_str());
1276 } else {
1277 string adjLabel = "AdjLabel";
1278 StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, adjLabel);
1279
1280 (void)dprintf(rawParamFd_, "%s %s %s %s %s\n", pid.c_str(),
1281 totalPss.c_str(), unMappedGL.c_str(), adjLabel.c_str(), name.c_str());
1282 }
1283 }
1284
GetMemoryInfoInit(StringMatrix result)1285 bool MemoryInfo::GetMemoryInfoInit(StringMatrix result)
1286 {
1287 if (!isReady_) {
1288 memUsages_.clear();
1289 pids_.clear();
1290 totalGL_ = 0;
1291 totalGraph_ = 0;
1292 AddMemByProcessTitle(result, "PID");
1293 if (!GetPids()) {
1294 DUMPER_HILOGE(MODULE_SERVICE, "GetPids error!\n");
1295 return false;
1296 }
1297 isReady_ = true;
1298 }
1299 return true;
1300 }
1301
GetMemoryUsageInfo(StringMatrix result)1302 void MemoryInfo::GetMemoryUsageInfo(StringMatrix result)
1303 {
1304 MemInfoData::MemUsage usage;
1305 MemoryUtil::GetInstance().InitMemUsage(usage);
1306 for (auto pid : pids_) {
1307 if (GetMemByProcessPid(pid, usage)) {
1308 memUsages_.push_back(usage);
1309 adjMemResult_[usage.adjLabel].push_back(usage);
1310 totalGL_ += usage.gl;
1311 totalGraph_ += usage.graph;
1312 totalDma_ += usage.dma;
1313 MemUsageToMatrix(usage, result);
1314 } else {
1315 DUMPER_HILOGE(MODULE_SERVICE, "Get smaps_rollup error! pid = %{public}d\n", static_cast<int>(pid));
1316 }
1317 }
1318 }
1319
GetMemoryInfoNoPid(int fd,StringMatrix result)1320 DumpStatus MemoryInfo::GetMemoryInfoNoPid(int fd, StringMatrix result)
1321 {
1322 std::lock_guard<std::mutex> lock(mutex_);
1323 rawParamFd_ = fd;
1324 (void)dprintf(rawParamFd_, "%s\n", MEMORY_LINE.c_str());
1325 if (!GetMemoryInfoInit(result)) {
1326 return DUMP_FAIL;
1327 }
1328
1329 if (!dumpSmapsOnStart_) {
1330 dumpSmapsOnStart_ = true;
1331 std::promise<GroupMap> promise;
1332 fut_ = promise.get_future();
1333 std::thread([promise = std::move(promise), this]() mutable {
1334 GroupMap groupMap;
1335 std::vector<int32_t> pids(this->pids_);
1336 for (auto pid : pids) {
1337 GetSmapsInfoNoPid(pid, groupMap);
1338 }
1339 promise.set_value(groupMap);
1340 }).detach();
1341 }
1342 GetMemoryUsageInfo(result);
1343 return DealResult(result);
1344 }
1345
GetMemoryInfoPrune(int fd,StringMatrix result)1346 DumpStatus MemoryInfo::GetMemoryInfoPrune(int fd, StringMatrix result)
1347 {
1348 std::lock_guard<std::mutex> lock(mutex_);
1349 rawParamFd_ = fd;
1350 dumpPrune_ = true;
1351 (void)dprintf(rawParamFd_, "%s\n", MEMORY_LINE.c_str());
1352 if (!GetMemoryInfoInit(result)) {
1353 return DUMP_FAIL;
1354 }
1355 GetMemoryUsageInfo(result);
1356 return DUMP_OK;
1357 }
1358
DealResult(StringMatrix result)1359 DumpStatus MemoryInfo::DealResult(StringMatrix result)
1360 {
1361 ValueMap meminfoResult;
1362 if (!GetMeminfo(meminfoResult)) {
1363 DUMPER_HILOGE(MODULE_SERVICE, "Get meminfo error\n");
1364 return DUMP_FAIL;
1365 }
1366
1367 GetSortedMemoryInfoNoPid(result);
1368 SaveStringToFd(rawParamFd_, "\n");
1369 #ifdef HIDUMPER_MEMMGR_ENABLE
1370 GetMemoryByAdj(result);
1371 #endif
1372 SaveStringToFd(rawParamFd_, "\n");
1373
1374 GroupMap smapsResult = fut_.get();
1375
1376 GetPssTotal(smapsResult, result);
1377 SaveStringToFd(rawParamFd_, "\n");
1378
1379 GetRamUsage(smapsResult, meminfoResult, result);
1380 SaveStringToFd(rawParamFd_, "\n");
1381
1382 GetRamCategory(smapsResult, meminfoResult, result);
1383 SaveStringToFd(rawParamFd_, "\n");
1384
1385 GetPurgTotal(meminfoResult, result);
1386
1387 isReady_ = false;
1388 dumpSmapsOnStart_ = false;
1389 memUsages_.clear();
1390 smapsResult.clear();
1391 return DUMP_OK;
1392 }
1393
GetSortedMemoryInfoNoPid(StringMatrix result)1394 void MemoryInfo::GetSortedMemoryInfoNoPid(StringMatrix result)
1395 {
1396 SaveStringToFd(rawParamFd_, "\n");
1397 AddMemByProcessTitle(result, "Size");
1398
1399 std::sort(memUsages_.begin(), memUsages_.end(),
1400 [] (MemInfoData::MemUsage &left, MemInfoData::MemUsage &right) {
1401 if (right.pss + right.swapPss != left.pss + left.swapPss) {
1402 return right.pss + right.swapPss < left.pss + left.swapPss;
1403 }
1404 if (right.vss != left.vss) {
1405 return right.vss < left.vss;
1406 }
1407 if (right.rss != left.rss) {
1408 return right.rss < left.rss;
1409 }
1410 if (right.uss != left.uss) {
1411 return right.uss < left.uss;
1412 }
1413 return right.pid < left.pid;
1414 });
1415
1416 for (auto &memUsage : memUsages_) {
1417 MemUsageToMatrix(memUsage, result);
1418 }
1419 }
1420
1421 #ifdef HIDUMPER_MEMMGR_ENABLE
GetMemoryByAdj(StringMatrix result)1422 void MemoryInfo::GetMemoryByAdj(StringMatrix result)
1423 {
1424 SaveStringToFd(rawParamFd_, "Total Pss by OOM adjustment:\n");
1425
1426 vector<string> reclaimPriority_;
1427 for (auto reclaim : Memory::ReclaimPriorityMapping) {
1428 reclaimPriority_.push_back(reclaim.second);
1429 }
1430 reclaimPriority_.push_back(Memory::RECLAIM_PRIORITY_UNKNOWN_DESC);
1431
1432 for (const auto &adjLabel : reclaimPriority_) {
1433 vector<MemInfoData::MemUsage> memUsages = adjMemResult_[adjLabel];
1434 vector<string> label;
1435 if (memUsages.size() == 0) {
1436 SaveStringToFd(rawParamFd_, adjLabel + ": " + AddKbUnit(0) + "\n");
1437 continue;
1438 }
1439 uint64_t totalPss = accumulate(memUsages.begin(), memUsages.end(), (uint64_t)0,
1440 [] (uint64_t a, MemInfoData::MemUsage &b) {
1441 return a + b.pss + b.swapPss;
1442 });
1443 SaveStringToFd(rawParamFd_, adjLabel + ": " + AddKbUnit(totalPss) + "\n");
1444
1445 std::sort(memUsages.begin(), memUsages.end(),
1446 [] (MemInfoData::MemUsage &left, MemInfoData::MemUsage &right) {
1447 return right.pss + right.swapPss < left.pss + left.swapPss;
1448 });
1449 for (const auto &memUsage : memUsages) {
1450 string name = PRE_BLANK + memUsage.name + "(pid=" + to_string(memUsage.pid) + "): ";
1451 StringUtils::GetInstance().SetWidth(NAME_AND_PID_WIDTH, BLANK_, true, name);
1452 name += AddKbUnit(memUsage.pss + memUsage.swapPss);
1453 if (memUsage.swapPss > 0) {
1454 name += " (" + to_string(memUsage.swapPss) + " kB in SwapPss)";
1455 }
1456 SaveStringToFd(rawParamFd_, name + "\n");
1457 }
1458 }
1459 }
1460 #endif
1461
SetPss(MemInfoData::MemInfo & meminfo,uint64_t value)1462 void MemoryInfo::SetPss(MemInfoData::MemInfo &meminfo, uint64_t value)
1463 {
1464 meminfo.pss += value;
1465 }
1466
SetSharedClean(MemInfoData::MemInfo & meminfo,uint64_t value)1467 void MemoryInfo::SetSharedClean(MemInfoData::MemInfo &meminfo, uint64_t value)
1468 {
1469 meminfo.sharedClean += value;
1470 }
1471
SetSharedDirty(MemInfoData::MemInfo & meminfo,uint64_t value)1472 void MemoryInfo::SetSharedDirty(MemInfoData::MemInfo &meminfo, uint64_t value)
1473 {
1474 meminfo.sharedDirty += value;
1475 }
1476
SetPrivateClean(MemInfoData::MemInfo & meminfo,uint64_t value)1477 void MemoryInfo::SetPrivateClean(MemInfoData::MemInfo &meminfo, uint64_t value)
1478 {
1479 meminfo.privateClean += value;
1480 }
1481
SetPrivateDirty(MemInfoData::MemInfo & meminfo,uint64_t value)1482 void MemoryInfo::SetPrivateDirty(MemInfoData::MemInfo &meminfo, uint64_t value)
1483 {
1484 meminfo.privateDirty += value;
1485 }
1486
SetSwap(MemInfoData::MemInfo & meminfo,uint64_t value)1487 void MemoryInfo::SetSwap(MemInfoData::MemInfo &meminfo, uint64_t value)
1488 {
1489 meminfo.swap += value;
1490 }
1491
SetSwapPss(MemInfoData::MemInfo & meminfo,uint64_t value)1492 void MemoryInfo::SetSwapPss(MemInfoData::MemInfo &meminfo, uint64_t value)
1493 {
1494 meminfo.swapPss += value;
1495 }
SetHeapSize(MemInfoData::MemInfo & meminfo,uint64_t value)1496 void MemoryInfo::SetHeapSize(MemInfoData::MemInfo &meminfo, uint64_t value)
1497 {
1498 meminfo.heapSize += value;
1499 }
1500
SetHeapAlloc(MemInfoData::MemInfo & meminfo,uint64_t value)1501 void MemoryInfo::SetHeapAlloc(MemInfoData::MemInfo &meminfo, uint64_t value)
1502 {
1503 meminfo.heapAlloc += value;
1504 }
1505
SetHeapFree(MemInfoData::MemInfo & meminfo,uint64_t value)1506 void MemoryInfo::SetHeapFree(MemInfoData::MemInfo &meminfo, uint64_t value)
1507 {
1508 meminfo.heapFree += value;
1509 }
1510 } // namespace HiviewDFX
1511 } // namespace OHOS