• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #include <dlfcn.h>
18 #include <cinttypes>
19 #include <fstream>
20 #include <numeric>
21 #include <thread>
22 #include <v1_0/imemory_tracker_interface.h>
23 
24 #include "dump_common_utils.h"
25 #include "dump_utils.h"
26 #include "executor/memory/get_cma_info.h"
27 #include "executor/memory/get_hardware_info.h"
28 #include "executor/memory/get_kernel_info.h"
29 #include "executor/memory/get_process_info.h"
30 #include "executor/memory/get_ram_info.h"
31 #include "executor/memory/memory_util.h"
32 #include "executor/memory/parse/parse_meminfo.h"
33 #include "executor/memory/parse/parse_smaps_rollup_info.h"
34 #include "executor/memory/parse/parse_smaps_info.h"
35 #include "file_ex.h"
36 #include "hdf_base.h"
37 #include "hilog_wrapper.h"
38 #ifdef HIDUMPER_MEMMGR_ENABLE
39 #include "mem_mgr_constant.h"
40 #endif
41 #include "securec.h"
42 #include "string_ex.h"
43 #include "util/string_utils.h"
44 #include "util/file_utils.h"
45 
46 using namespace std;
47 using namespace OHOS::HDI::Memorytracker::V1_0;
48 
49 namespace OHOS {
50 namespace HiviewDFX {
51 static const int PAGETAG_MIN_LEN = 2; // page tag min length
52 static const std::string LIB = "libai_mnt_client.so";
53 
54 static const std::string UNKNOWN_PROCESS = "unknown";
55 static const std::string PRE_BLANK = "   ";
56 static const std::string MEMORY_LINE = "-------------------------------[memory]-------------------------------";
57 constexpr char HIAI_MEM_INFO_FN[] = "HIAI_Memory_QueryAllUserAllocatedMemInfo";
58 using HiaiFunc = int (*)(MemInfoData::HiaiUserAllocatedMemInfo*, int, int*);
59 
MemoryInfo()60 MemoryInfo::MemoryInfo()
61 {
62     methodVec_.clear();
63     methodVec_.push_back(make_pair(MEMINFO_PSS,
64         bind(&MemoryInfo::SetPss, this, placeholders::_1, placeholders::_2)));
65     methodVec_.push_back(make_pair(MEMINFO_SHARED_CLEAN,
66         bind(&MemoryInfo::SetSharedClean, this, placeholders::_1, placeholders::_2)));
67     methodVec_.push_back(make_pair(MEMINFO_SHARED_DIRTY,
68         bind(&MemoryInfo::SetSharedDirty, this, placeholders::_1, placeholders::_2)));
69     methodVec_.push_back(make_pair(MEMINFO_PRIVATE_CLEAN,
70         bind(&MemoryInfo::SetPrivateClean, this, placeholders::_1, placeholders::_2)));
71     methodVec_.push_back(make_pair(MEMINFO_PRIVATE_DIRTY,
72         bind(&MemoryInfo::SetPrivateDirty, this, placeholders::_1, placeholders::_2)));
73     methodVec_.push_back(make_pair(MEMINFO_SWAP,
74         bind(&MemoryInfo::SetSwap, this, placeholders::_1, placeholders::_2)));
75     methodVec_.push_back(make_pair(MEMINFO_SWAP_PSS,
76         bind(&MemoryInfo::SetSwapPss, this, placeholders::_1, placeholders::_2)));
77     methodVec_.push_back(make_pair(MEMINFO_HEAP_SIZE,
78         bind(&MemoryInfo::SetHeapSize, this, placeholders::_1, placeholders::_2)));
79     methodVec_.push_back(make_pair(MEMINFO_HEAP_ALLOC,
80         bind(&MemoryInfo::SetHeapAlloc, this, placeholders::_1, placeholders::_2)));
81     methodVec_.push_back(make_pair(MEMINFO_HEAP_FREE,
82         bind(&MemoryInfo::SetHeapFree, this, placeholders::_1, placeholders::_2)));
83 }
84 
~MemoryInfo()85 MemoryInfo::~MemoryInfo()
86 {
87 }
88 
InsertMemoryTitle(StringMatrix result)89 void MemoryInfo::InsertMemoryTitle(StringMatrix result)
90 {
91     // Pss        Shared   ---- this line is line1
92     // Total      Clean    ---- this line is line2
93     // (KB)         (KB)    ---- this line is line3
94     // -----      ------   ---- this line is line4
95 
96     vector<string> line1;
97     vector<string> line2;
98     vector<string> line3;
99     vector<string> line4;
100 
101     string space = " ";
102     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, space);
103 
104     string separator = "-";
105     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, SEPARATOR_, false, separator);
106 
107     string unit = "(" + MemoryUtil::GetInstance().KB_UNIT_ + " )";
108     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, unit);
109 
110     // Add  spaces at the beginning of the line
111     line1.push_back(space + BLANK_);
112     line2.push_back(space + BLANK_);
113     line3.push_back(space + BLANK_);
114     line4.push_back(space);
115 
116     for (string str : MemoryFilter::GetInstance().TITLE_HAS_PID_) {
117         vector<string> types;
118         StringUtils::GetInstance().StringSplit(str, "_", types);
119         if (types.size() == TYPE_SIZE) {
120             string title1 = types.at(0);
121             StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, title1);
122             line1.push_back(title1 + BLANK_);
123 
124             string title2 = types.at(1);
125             StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, title2);
126             line2.push_back(title2 + BLANK_);
127             line3.push_back(unit + BLANK_);
128             line4.push_back(separator + SEPARATOR_);
129         }
130     }
131     result->push_back(line1);
132     result->push_back(line2);
133     result->push_back(line3);
134     result->push_back(line4);
135 }
136 
UpdateResult(const int32_t & pid,const unique_ptr<ProcessMemoryDetail> & processMemoryDetail,unique_ptr<MemoryDetail> & nativeHeapDetail,StringMatrix result)137 void MemoryInfo::UpdateResult(const int32_t& pid, const unique_ptr<ProcessMemoryDetail>& processMemoryDetail,
138     unique_ptr<MemoryDetail>& nativeHeapDetail, StringMatrix result)
139 {
140     unique_ptr<MallHeapInfo> mallocHeapInfo = make_unique<MallHeapInfo>();
141     unique_ptr<GetHeapInfo> getHeapInfo = make_unique<GetHeapInfo>();
142     getHeapInfo->GetMallocHeapInfo(pid, mallocHeapInfo);
143     unique_ptr<MemoryDetail> anonPageDetail = make_unique<MemoryDetail>();
144     unique_ptr<MemoryDetail> filePageDetail = make_unique<MemoryDetail>();
145     vector<MemoryDetail> memoryDetails = processMemoryDetail->details;
146     map<string, unique_ptr<MemoryDetail>> allDetailMap;
147     for (const auto& memoryDetail : memoryDetails) {
148         MemoryClass memoryClass = memoryDetail.memoryClass;
149         if (static_cast<int>(memoryClass) < 0 || static_cast<size_t>(memoryClass) > MEMORY_CLASS_VEC.size()) {
150             DUMPER_HILOGE(MODULE_SERVICE, "memoryClass:%{public}d is not exist", memoryClass);
151             continue;
152         }
153         string memoryClassStr = MEMORY_CLASS_VEC[static_cast<int>(memoryClass)];
154         unique_ptr<MemoryDetail> tempDetail = make_unique<MemoryDetail>(memoryDetail);
155         if (memoryClassStr == "graph") {
156             GetGraphicsMemoryByDetail(tempDetail, result);
157         } else if (memoryClassStr == MemoryFilter::GetInstance().NATIVE_HEAP_LABEL) {
158             nativeHeapDetail = make_unique<MemoryDetail>(memoryDetail);
159         } else if (memoryClassStr == MEMINFO_OTHER) {
160             UpdatePageDetail(anonPageDetail, filePageDetail, tempDetail);
161             tempDetail = std::move(anonPageDetail);
162             memoryClassStr = MEMINFO_ANONPAGE_OTHER;
163         }
164         auto it = std::find(MEMORY_PRINT_ORDER_VEC.begin(), MEMORY_PRINT_ORDER_VEC.end(), memoryClassStr);
165         if (it!= MEMORY_PRINT_ORDER_VEC.end()) {
166             allDetailMap[memoryClassStr] = std::move(tempDetail);
167         }
168     }
169     for (const auto &classStr : MEMORY_PRINT_ORDER_VEC) {
170         auto it = allDetailMap.find(classStr);
171         if (it != allDetailMap.end()) {
172             SetDetailRet(classStr, it->second, mallocHeapInfo, result);
173         }
174     }
175     SetDetailRet(MEMINFO_FILEPAGE_OTHER, filePageDetail, mallocHeapInfo, result);
176     UpdateTotalDetail(processMemoryDetail, mallocHeapInfo, result);
177 }
178 
UpdatePageDetail(std::unique_ptr<MemoryDetail> & anonPageDetail,std::unique_ptr<MemoryDetail> & filePageDetail,const std::unique_ptr<MemoryDetail> & tempDetail)179 void MemoryInfo::UpdatePageDetail(std::unique_ptr<MemoryDetail>& anonPageDetail,
180                                   std::unique_ptr<MemoryDetail>& filePageDetail,
181                                   const std::unique_ptr<MemoryDetail>& tempDetail)
182 {
183     if (!tempDetail) {
184         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
185         return;
186     }
187     vector<MemoryItem> memoryItems = tempDetail->items;
188     for (const auto& memoryItem : memoryItems) {
189         int32_t iNode = memoryItem.iNode;
190         if (iNode == 0) {
191             anonPageDetail->totalPss += memoryItem.pss;
192             anonPageDetail->totalSharedClean += memoryItem.sharedClean;
193             anonPageDetail->totalSharedDirty += memoryItem.sharedDirty;
194             anonPageDetail->totalPrivateClean += memoryItem.privateClean;
195             anonPageDetail->totalPrivateDirty += memoryItem.privateDirty;
196             anonPageDetail->totalSwap += memoryItem.swap;
197             anonPageDetail->totalSwapPss += memoryItem.swapPss;
198         } else {
199             filePageDetail->totalPss += memoryItem.pss;
200             filePageDetail->totalSharedClean += memoryItem.sharedClean;
201             filePageDetail->totalSharedDirty += memoryItem.sharedDirty;
202             filePageDetail->totalPrivateClean += memoryItem.privateClean;
203             filePageDetail->totalPrivateDirty += memoryItem.privateDirty;
204             filePageDetail->totalSwap += memoryItem.swap;
205             filePageDetail->totalSwapPss += memoryItem.swapPss;
206         }
207     }
208 }
209 
SetDetailRet(const std::string & memoryClassStr,const std::unique_ptr<MemoryDetail> & detail,const std::unique_ptr<MallHeapInfo> & heapInfo,StringMatrix result)210 void MemoryInfo::SetDetailRet(const std::string& memoryClassStr, const std::unique_ptr<MemoryDetail>& detail,
211                               const std::unique_ptr<MallHeapInfo>& heapInfo, StringMatrix result)
212 {
213     if (!detail) {
214         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
215         return;
216     }
217     vector<string> tempResult;
218     SetValueForRet(memoryClassStr, tempResult);
219     SetValueForRet(to_string(detail->totalPss), tempResult);
220     SetValueForRet(to_string(detail->totalSharedClean), tempResult);
221     SetValueForRet(to_string(detail->totalSharedDirty), tempResult);
222     SetValueForRet(to_string(detail->totalPrivateClean), tempResult);
223     SetValueForRet(to_string(detail->totalPrivateDirty), tempResult);
224     SetValueForRet(to_string(detail->totalSwap), tempResult);
225     SetValueForRet(to_string(detail->totalSwapPss), tempResult);
226     if (memoryClassStr == MemoryFilter::GetInstance().NATIVE_HEAP_LABEL) {
227         SetValueForRet(to_string(heapInfo->size), tempResult);
228         SetValueForRet(to_string(heapInfo->alloc), tempResult);
229         SetValueForRet(to_string(heapInfo->free), tempResult);
230     } else {
231         for (int i = 0; i < MALLOC_HEAP_TYPES; i++) {
232             SetValueForRet(ZERO, tempResult);
233         }
234     }
235     result->push_back(tempResult);
236 }
237 
SetValueForRet(const std::string & value,std::vector<std::string> & tempResult)238 void MemoryInfo::SetValueForRet(const std::string& value, std::vector<std::string>& tempResult)
239 {
240     std::string tempStr = value;
241     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, tempStr);
242     tempResult.push_back(tempStr + BLANK_);
243 }
244 
UpdateTotalDetail(const std::unique_ptr<ProcessMemoryDetail> & detail,const std::unique_ptr<MallHeapInfo> & heapInfo,StringMatrix result)245 void MemoryInfo::UpdateTotalDetail(const std::unique_ptr<ProcessMemoryDetail>& detail,
246                                    const std::unique_ptr<MallHeapInfo>& heapInfo, StringMatrix result)
247 {
248     if (!detail) {
249         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
250         return;
251     }
252     vector<string> lines;
253     vector<string> values;
254     uint64_t totalPrivateDirty = static_cast<uint64_t>(detail->totalPrivateDirty) + graphicsMemory_.gl +
255         graphicsMemory_.graph;
256     MemoryUtil::GetInstance().SetMemTotalValue(MEMINFO_TOTAL, lines, values);
257     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalAllPss), lines, values);
258     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSharedClean), lines, values);
259     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSharedDirty), lines, values);
260     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalPrivateClean), lines, values);
261     MemoryUtil::GetInstance().SetMemTotalValue(to_string(totalPrivateDirty), lines, values);
262     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSwap), lines, values);
263     MemoryUtil::GetInstance().SetMemTotalValue(to_string(detail->totalSwapPss), lines, values);
264     MemoryUtil::GetInstance().SetMemTotalValue(to_string(heapInfo->size), lines, values);
265     MemoryUtil::GetInstance().SetMemTotalValue(to_string(heapInfo->alloc), lines, values);
266     MemoryUtil::GetInstance().SetMemTotalValue(to_string(heapInfo->free), lines, values);
267 
268     // delete the last separator
269     if (!lines.empty()) {
270         lines.pop_back();
271         string separator = "-";
272         StringUtils::GetInstance().SetWidth(LINE_WIDTH_, SEPARATOR_, false, separator);
273         lines.push_back(separator);
274     }
275     result->push_back(lines);
276     result->push_back(values);
277 }
278 
GetMemoryInfoByPid(const int32_t & pid,StringMatrix result)279 bool MemoryInfo::GetMemoryInfoByPid(const int32_t &pid, StringMatrix result)
280 {
281     std::lock_guard<std::mutex> lock(mutex_);
282     InsertMemoryTitle(result);
283     GetResult(pid, result);
284     GetPurgByPid(pid, result);
285     GetDma(graphicsMemory_.graph, result);
286     GetHiaiServerIon(pid, result);
287     return true;
288 }
289 
GetResult(const int32_t & pid,StringMatrix result)290 void MemoryInfo::GetResult(const int32_t& pid, StringMatrix result)
291 {
292     DUMPER_HILOGD(MODULE_SERVICE, "CollectProcessMemoryDetail pid:%{public}d start", pid);
293     std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create();
294     CollectResult<ProcessMemoryDetail> collectRet;
295     collectRet = collector->CollectProcessMemoryDetail(pid, true);
296     if (collectRet.retCode != UCollect::UcError::SUCCESS) {
297         DUMPER_HILOGE(MODULE_SERVICE, "collect process memory error, ret:%{public}d", collectRet.retCode);
298         return;
299     }
300     unique_ptr<ProcessMemoryDetail> processMemoryDetail = make_unique<ProcessMemoryDetail>(collectRet.data);
301     if (!processMemoryDetail) {
302         DUMPER_HILOGE(MODULE_SERVICE, "processMemoryDetail is nullptr");
303         return;
304     }
305     DUMPER_HILOGD(MODULE_SERVICE, "CollectProcessMemoryDetail pid:%{public}d end", pid);
306     unique_ptr<MemoryDetail> nativeHeapDetail = {nullptr};
307     UpdateResult(pid, processMemoryDetail, nativeHeapDetail, result);
308     GetNativeHeap(nativeHeapDetail, result);
309 }
310 
GetGraphicsMemoryByDetail(const std::unique_ptr<MemoryDetail> & detail,StringMatrix result)311 void MemoryInfo::GetGraphicsMemoryByDetail(const std::unique_ptr<MemoryDetail>& detail, StringMatrix result)
312 {
313     if (!detail) {
314         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
315         return;
316     }
317     vector<MemoryItem> memoryItems = detail->items;
318     for (const auto& memoryItem : memoryItems) {
319         MemoryItemType memoryItemType = memoryItem.type;
320         auto info = GRAPHIC_MAP.find(memoryItemType);
321         if (info == GRAPHIC_MAP.end()) {
322             DUMPER_HILOGE(MODULE_SERVICE, "memoryItemType = %{public}d is not exist", memoryItemType);
323             continue;
324         }
325         string type = info->second;
326         if (type == MemoryFilter::GetInstance().GL_OUT_LABEL) {
327             graphicsMemory_.gl = memoryItem.pss;
328         } else if (type == MemoryFilter::GetInstance().GRAPH_OUT_LABEL) {
329             graphicsMemory_.graph = memoryItem.pss;
330         }
331     }
332     UpdateGraphicsMemoryRet(MemoryFilter::GetInstance().GL_OUT_LABEL, graphicsMemory_.gl, result);
333     UpdateGraphicsMemoryRet(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, graphicsMemory_.graph, result);
334 }
335 
UpdateGraphicsMemoryRet(const string & title,const uint64_t & value,StringMatrix result)336 void MemoryInfo::UpdateGraphicsMemoryRet(const string& title, const uint64_t& value, StringMatrix result)
337 {
338     map<string, uint64_t> valueMap;
339     valueMap.insert(pair<string, uint64_t>(MEMINFO_PSS, value));
340     valueMap.insert(pair<string, uint64_t>(MEMINFO_PRIVATE_DIRTY, value));
341     vector<string> tempResult;
342     string tempTitle = title;
343     StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, tempTitle);
344     tempResult.push_back(tempTitle + BLANK_);
345     for (const auto &tag : MemoryFilter::GetInstance().VALUE_WITH_PID) {
346         auto it = valueMap.find(tag);
347         string value = ZERO;
348         if (it != valueMap.end()) {
349             value = to_string(it->second);
350         }
351         StringUtils::GetInstance().SetWidth(LINE_WIDTH_, BLANK_, false, value);
352         tempResult.push_back(value + BLANK_);
353     }
354     result->push_back(tempResult);
355 }
356 
AddKbUnit(const uint64_t & value) const357 string MemoryInfo::AddKbUnit(const uint64_t &value) const
358 {
359     return to_string(value) + MemoryUtil::GetInstance().KB_UNIT_;
360 }
361 
GetSmapsInfoNoPid(const int32_t & pid,GroupMap & result)362 bool MemoryInfo::GetSmapsInfoNoPid(const int32_t &pid, GroupMap &result)
363 {
364     GroupMap NativeMap;
365     unique_ptr<ParseSmapsInfo> parseSmapsInfo = make_unique<ParseSmapsInfo>();
366     return parseSmapsInfo->GetInfo(MemoryFilter::NOT_SPECIFIED_PID, pid, NativeMap, result);
367 }
368 
GetMeminfo(ValueMap & result)369 bool MemoryInfo::GetMeminfo(ValueMap &result)
370 {
371     unique_ptr<ParseMeminfo> parseMeminfo = make_unique<ParseMeminfo>();
372     return parseMeminfo->GetMeminfo(result);
373 }
374 
GetHardWareUsage(StringMatrix result)375 bool MemoryInfo::GetHardWareUsage(StringMatrix result)
376 {
377     uint64_t value;
378     unique_ptr<GetHardwareInfo> getHardwareInfo = make_unique<GetHardwareInfo>();
379     if (getHardwareInfo->GetHardwareUsage(value)) {
380         string title = "Hardware Usage:";
381         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
382         SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
383         return true;
384     }
385     return false;
386 }
387 
GetCMAUsage(StringMatrix result)388 bool MemoryInfo::GetCMAUsage(StringMatrix result)
389 {
390     uint64_t value = 0;
391     unique_ptr<GetCMAInfo> getCMAInfo = make_unique<GetCMAInfo>();
392     bool success = getCMAInfo->GetUsed(value);
393     if (success) {
394         string title = "CMA Usage:";
395         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
396         SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
397     }
398     return success;
399 }
400 
GetKernelUsage(const ValueMap & infos,StringMatrix result)401 bool MemoryInfo::GetKernelUsage(const ValueMap &infos, StringMatrix result)
402 {
403     uint64_t value = 0;
404     unique_ptr<GetKernelInfo> getGetKernelInfo = make_unique<GetKernelInfo>();
405     bool success = getGetKernelInfo->GetKernel(infos, value);
406     if (success) {
407         string title = "Kernel Usage:";
408         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
409         SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
410     }
411     return success;
412 }
413 
GetProcesses(const GroupMap & infos,StringMatrix result)414 void MemoryInfo::GetProcesses(const GroupMap &infos, StringMatrix result)
415 {
416     uint64_t value = 0;
417 
418     unique_ptr<GetProcessInfo> getProcessInfo = make_unique<GetProcessInfo>();
419     value = getProcessInfo->GetProcess(infos);
420 
421     string title = "Processes Usage:";
422     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, title);
423     SaveStringToFd(rawParamFd_, title + AddKbUnit(value) + "\n");
424 }
425 
GetPssTotal(const GroupMap & infos,StringMatrix result)426 void MemoryInfo::GetPssTotal(const GroupMap &infos, StringMatrix result)
427 {
428     SaveStringToFd(rawParamFd_, "Total Pss by Category:\n");
429     vector<pair<string, uint64_t>> filePage;
430     vector<pair<string, uint64_t>> anonPage;
431     for (const auto &info : infos) {
432         vector<string> pageTag;
433         StringUtils::GetInstance().StringSplit(info.first, "#", pageTag);
434         if (pageTag.size() < PAGETAG_MIN_LEN) {
435             DUMPER_HILOGE(MODULE_COMMON, "Infos are invalid, info.first: %{public}s", info.first.c_str());
436             continue;
437         }
438         string group = pageTag[1];
439         auto &valueMap = info.second;
440         uint64_t pssValue = 0;
441         for (const auto &str : MemoryFilter::GetInstance().CALC_PSS_TOTAL_) {
442             auto it = valueMap.find(str);
443             if (it != valueMap.end()) {
444                 pssValue += it->second;
445             }
446         }
447 
448         if (pageTag[0] == MemoryFilter::GetInstance().FILE_PAGE_TAG) {
449             filePage.push_back(make_pair(group, pssValue));
450         } else {
451             anonPage.push_back(make_pair(group, pssValue));
452         }
453     }
454     PairToStringMatrix(MemoryFilter::GetInstance().FILE_PAGE_TAG, filePage, result);
455     PairToStringMatrix(MemoryFilter::GetInstance().ANON_PAGE_TAG, anonPage, result);
456 
457     vector<pair<string, uint64_t>> gpuValue;
458     gpuValue.push_back(make_pair(MemoryFilter::GetInstance().GL_OUT_LABEL, totalGL_));
459     PairToStringMatrix(MemoryFilter::GetInstance().GPU_TAG, gpuValue, result);
460 
461     vector<pair<string, uint64_t>> graphValue;
462     graphValue.push_back(make_pair(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, totalGraph_));
463     PairToStringMatrix(MemoryFilter::GetInstance().GRAPH_OUT_LABEL, graphValue, result);
464 
465     vector<pair<string, uint64_t>> dmaValue;
466     dmaValue.push_back(make_pair(MemoryFilter::GetInstance().DMA_OUT_LABEL, totalDma_));
467     PairToStringMatrix(MemoryFilter::GetInstance().DMA_TAG, dmaValue, result);
468 }
469 
PairToStringMatrix(const string & titleStr,vector<pair<string,uint64_t>> & vec,StringMatrix result)470 void MemoryInfo::PairToStringMatrix(const string &titleStr, vector<pair<string, uint64_t>> &vec, StringMatrix result)
471 {
472     uint64_t totalPss = accumulate(vec.begin(), vec.end(), (uint64_t)0, [] (uint64_t a, pair<string, uint64_t> &b) {
473         return a + b.second;
474     });
475     SaveStringToFd(rawParamFd_, titleStr + "(" + AddKbUnit(totalPss) + "):\n");
476 
477     std::sort(vec.begin(), vec.end(),
478         [] (pair<string, uint64_t> &left, pair<string, uint64_t> &right) {
479         return right.second < left.second;
480     });
481     for (const auto &pair : vec) {
482         string pssStr = AddKbUnit(pair.second);
483         StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, pssStr);
484         SaveStringToFd(rawParamFd_, pssStr + " : " + pair.first + "\n");
485     }
486 }
487 
GetRamUsage(const GroupMap & smapsinfos,const ValueMap & meminfo,StringMatrix result)488 void MemoryInfo::GetRamUsage(const GroupMap &smapsinfos, const ValueMap &meminfo, StringMatrix result)
489 {
490     unique_ptr<GetRamInfo> getRamInfo = make_unique<GetRamInfo>();
491     GetRamInfo::Ram ram = getRamInfo->GetRam(smapsinfos, meminfo);
492 
493     string totalTitle = "Total RAM:";
494     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalTitle);
495     SaveStringToFd(rawParamFd_, totalTitle + AddKbUnit(ram.total) + "\n");
496 
497     string freeTitle = "Free RAM:";
498     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, freeTitle);
499     SaveStringToFd(rawParamFd_, freeTitle + AddKbUnit(ram.free) +
500         " (" + to_string(ram.cachedInfo) + " cached + " + to_string(ram.freeInfo) + " free)\n");
501 
502     string usedTitle = "Used RAM:";
503     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, usedTitle);
504     SaveStringToFd(rawParamFd_, usedTitle + AddKbUnit(ram.used) +
505         " (" + to_string(ram.totalPss) + " total pss + " + to_string(ram.kernelUsed) + " kernel)\n");
506 
507     string lostTitle = "Lost RAM:";
508     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, lostTitle);
509     SaveStringToFd(rawParamFd_, lostTitle + to_string(ram.lost) + MemoryUtil::GetInstance().KB_UNIT_ + "\n");
510 }
511 
GetPurgTotal(const ValueMap & meminfo,StringMatrix result)512 void MemoryInfo::GetPurgTotal(const ValueMap &meminfo, StringMatrix result)
513 {
514     SaveStringToFd(rawParamFd_, "Total Purgeable:\n");
515 
516     uint64_t purgSumTotal = 0;
517     uint64_t purgPinTotal = 0;
518     auto purgSumActive = meminfo.find(MemoryFilter::GetInstance().PURG_SUM[0]);
519     auto purgSumInactive = meminfo.find(MemoryFilter::GetInstance().PURG_SUM[1]);
520     auto purgPinPined = meminfo.find(MemoryFilter::GetInstance().PURG_PIN[0]);
521     if (purgSumActive == meminfo.end() || purgSumInactive == meminfo.end() || purgPinPined == meminfo.end()) {
522         DUMPER_HILOGE(MODULE_SERVICE, "fail to get purg info \n");
523     } else {
524         purgSumTotal = purgSumActive->second + purgSumInactive->second;
525         purgPinTotal = purgPinPined->second;
526     }
527 
528     string totalPurgSumTitle = "Total PurgSum:";
529     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalPurgSumTitle);
530     SaveStringToFd(rawParamFd_, totalPurgSumTitle + AddKbUnit(purgSumTotal) + "\n");
531 
532     string totalPurgPinTitle = "Total PurgPin:";
533     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, totalPurgPinTitle);
534     SaveStringToFd(rawParamFd_, totalPurgPinTitle + AddKbUnit(purgPinTotal) + "\n");
535 }
536 
GetPurgByPid(const int32_t & pid,StringMatrix result)537 void MemoryInfo::GetPurgByPid(const int32_t &pid, StringMatrix result)
538 {
539     AddBlankLine(result);
540     vector<string> title;
541     title.push_back("Purgeable:");
542     result->push_back(title);
543 
544     vector<string> purgSum;
545     string purgSumTitle = MemoryFilter::GetInstance().PURGSUM_OUT_LABEL + ":";
546     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, purgSumTitle);
547     purgSum.push_back(purgSumTitle);
548     purgSum.push_back(AddKbUnit(GetProcValue(pid, MemoryFilter::GetInstance().PURGSUM_OUT_LABEL)));
549     result->push_back(purgSum);
550 
551     vector<string> purgPin;
552     string purgPinTitle = MemoryFilter::GetInstance().PURGPIN_OUT_LABEL + ":";
553     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, purgPinTitle);
554     purgPin.push_back(purgPinTitle);
555     purgPin.push_back(AddKbUnit(GetProcValue(pid, MemoryFilter::GetInstance().PURGPIN_OUT_LABEL)));
556     result->push_back(purgPin);
557 }
558 
GetNativeHeap(const std::unique_ptr<MemoryDetail> & detail,StringMatrix result)559 void MemoryInfo::GetNativeHeap(const std::unique_ptr<MemoryDetail>& detail, StringMatrix result)
560 {
561     if (!detail) {
562         DUMPER_HILOGE(MODULE_SERVICE, "detail is nullptr");
563         return;
564     }
565     AddBlankLine(result);
566     vector<string> title;
567     title.push_back(MemoryFilter::GetInstance().NATIVE_HEAP_LABEL + ":");
568     result->push_back(title);
569 
570     vector<MemoryItem> memoryItems = detail->items;
571     for (const auto& memoryItem : memoryItems) {
572         MemoryItemType memoryItemType = memoryItem.type;
573         auto info = NATIVE_HEAP_MAP.find(memoryItemType);
574         if (info == NATIVE_HEAP_MAP.end()) {
575             DUMPER_HILOGE(MODULE_SERVICE, "memoryItemType = %{public}d is not exist", memoryItemType);
576             continue;
577         }
578         string type = info->second;
579         auto it = memoryItemMap_.find(type);
580         if (it == memoryItemMap_.end()) {
581             memoryItemMap_.insert(pair<string, MemoryItem>(type, memoryItem));
582         } else {
583             it->second.pss += memoryItem.pss;
584             it->second.sharedClean += memoryItem.sharedClean;
585             it->second.sharedDirty += memoryItem.sharedDirty;
586             it->second.privateClean += memoryItem.privateClean;
587             it->second.privateDirty += memoryItem.privateDirty;
588             it->second.swap += memoryItem.swap;
589             it->second.swapPss += memoryItem.swapPss;
590         }
591     }
592     for (const auto& type: NATIVE_HEAP_TAG) {
593         auto it = memoryItemMap_.find(type);
594         if (it == memoryItemMap_.end()) {
595             continue;
596         }
597         string heapTitle = it->first;
598         unique_ptr<MemoryItem> item = make_unique<MemoryItem>(it->second);
599         SetNativeDetailRet(type, item, result);
600     }
601 }
602 
SetNativeDetailRet(const std::string & nativeClassStr,const std::unique_ptr<MemoryItem> & item,StringMatrix result)603 void MemoryInfo::SetNativeDetailRet(const std::string& nativeClassStr, const std::unique_ptr<MemoryItem>& item,
604                                     StringMatrix result)
605 {
606     vector<string> heap;
607     string heapTitle = nativeClassStr + ":";
608     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, heapTitle);
609     heap.push_back(heapTitle);
610     SetValueForRet(to_string(item->pss), heap);
611     SetValueForRet(to_string(item->sharedClean), heap);
612     SetValueForRet(to_string(item->sharedDirty), heap);
613     SetValueForRet(to_string(item->privateClean), heap);
614     SetValueForRet(to_string(item->privateDirty), heap);
615     SetValueForRet(to_string(item->swap), heap);
616     SetValueForRet(to_string(item->swapPss), heap);
617     for (int i = 0; i < MALLOC_HEAP_TYPES; i++) {
618         SetValueForRet(ZERO, heap);
619     }
620     result->push_back(heap);
621 }
622 
GetDma(const uint64_t & dmaValue,StringMatrix result)623 void MemoryInfo::GetDma(const uint64_t& dmaValue, StringMatrix result)
624 {
625     AddBlankLine(result);
626     vector<string> title;
627     title.push_back(MemoryFilter::GetInstance().DMA_TAG + ":");
628     result->push_back(title);
629 
630     vector<string> dma;
631     string dmaTitle = MemoryFilter::GetInstance().DMA_OUT_LABEL + ":";
632     StringUtils::GetInstance().SetWidth(RAM_WIDTH_, BLANK_, false, dmaTitle);
633     dma.push_back(dmaTitle);
634     dma.push_back(to_string(dmaValue) + MemoryUtil::GetInstance().KB_UNIT_);
635     result->push_back(dma);
636 }
637 
GetHiaiServerIon(const int32_t & pid,StringMatrix result)638 void MemoryInfo::GetHiaiServerIon(const int32_t &pid, StringMatrix result)
639 {
640     if (GetProcName(pid) != "hiaiserver") {
641         return;
642     }
643     void *handle = dlopen(LIB.c_str(), RTLD_LAZY);
644     if (handle == nullptr) {
645         DUMPER_HILOGE(MODULE_SERVICE, "fail to open %{public}s.", LIB.c_str());
646         return;
647     }
648     HiaiFunc pfn = reinterpret_cast<HiaiFunc>(dlsym(handle, HIAI_MEM_INFO_FN));
649     if (pfn == nullptr) {
650         DUMPER_HILOGE(MODULE_SERVICE, "fail to dlsym %{public}s.", HIAI_MEM_INFO_FN);
651         dlclose(handle);
652         return;
653     }
654     MemInfoData::HiaiUserAllocatedMemInfo memInfos[HIAI_MAX_QUERIED_USER_MEMINFO_LIMIT] = {};
655 
656     int realSize = 0;
657     pfn(memInfos, HIAI_MAX_QUERIED_USER_MEMINFO_LIMIT, &realSize);
658     if (realSize > 0) {
659         AddBlankLine(result);
660         vector<string> vecIon;
661         vecIon.push_back("HIAIServer ION:\n");
662         for (int i = 0; i < realSize; i++) {
663             vecIon.push_back(GetProcName(memInfos[i].pid) + "(" + to_string(memInfos[i].pid) + "):" +
664                              to_string(memInfos[i].size / BYTE_PER_KB) + " kB\n");
665         }
666         result->push_back(vecIon);
667     }
668     dlclose(handle);
669 }
670 
GetRamCategory(const GroupMap & smapsInfos,const ValueMap & meminfos,StringMatrix result)671 void MemoryInfo::GetRamCategory(const GroupMap &smapsInfos, const ValueMap &meminfos, StringMatrix result)
672 {
673     SaveStringToFd(rawParamFd_, "Total RAM by Category:\n");
674 
675     bool hardWareSuccess = GetHardWareUsage(result);
676     if (!hardWareSuccess) {
677         DUMPER_HILOGE(MODULE_SERVICE, "Get hardWare usage fail.\n");
678     }
679 
680     bool cmaSuccess = GetCMAUsage(result);
681     if (!cmaSuccess) {
682         DUMPER_HILOGE(MODULE_SERVICE, "Get CMA fail.\n");
683     }
684 
685     bool kernelSuccess = GetKernelUsage(meminfos, result);
686     if (!kernelSuccess) {
687         DUMPER_HILOGE(MODULE_SERVICE, "Get kernel usage fail.\n");
688     }
689 
690     GetProcesses(smapsInfos, result);
691 }
692 
AddBlankLine(StringMatrix result)693 void MemoryInfo::AddBlankLine(StringMatrix result)
694 {
695     vector<string> blank;
696     blank.push_back("\n");
697     result->push_back(blank);
698 }
699 
GetProcName(const int32_t & pid)700 string MemoryInfo::GetProcName(const int32_t &pid)
701 {
702     string procName = UNKNOWN_PROCESS;
703     DumpCommonUtils::GetProcessNameByPid(pid, procName);
704     if (procName == UNKNOWN_PROCESS) {
705         string path = "/proc/" + to_string(pid) + "/status";
706         procName = FileUtils::GetInstance().GetProcValue(pid, path, "Name");
707     }
708     return procName;
709 }
710 
GetProcValue(const int32_t & pid,const string & key)711 uint64_t MemoryInfo::GetProcValue(const int32_t &pid, const string& key)
712 {
713     string path = "/proc/" + to_string(pid) + "/status";
714     std::string value = FileUtils::GetInstance().GetProcValue(pid, path, key);
715     if (value == UNKNOWN_PROCESS) {
716         DUMPER_HILOGE(MODULE_SERVICE, "GetProcStatusValue failed");
717         return 0;
718     }
719     int number = 0;
720     value = value.substr(0, value.size() - 3); // 3: ' kB'
721     if (value.find_last_of(' ') != std::string::npos) {
722         value = value.substr(value.find_last_of(' ') + 1);
723     }
724     if (!StrToInt(value, number)) {
725         DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed, value: %{public}s", value.c_str());
726         return 0;
727     }
728     return static_cast<uint64_t>(number);
729 }
730 
731 #ifdef HIDUMPER_MEMMGR_ENABLE
GetProcessAdjLabel(const int32_t pid)732 string MemoryInfo::GetProcessAdjLabel(const int32_t pid)
733 {
734     string adjLabel = Memory::RECLAIM_PRIORITY_UNKNOWN_DESC;
735     string fillPath = "/proc/" + to_string(pid) + "/oom_score_adj";
736     if (!DumpUtils::PathIsValid(fillPath)) {
737         DUMPER_HILOGE(MODULE_COMMON, "GetProcessAdjLabel leave|false, PathIsValid");
738         return adjLabel;
739     }
740     auto fp = fopen(fillPath.c_str(), "rb");
741     if (fp == nullptr) {
742         DUMPER_HILOGE(MODULE_COMMON, "Open oom_score_adj failed.");
743         return adjLabel;
744     }
745     constexpr int bufSize = 128; // 128: buf size
746     char buf[bufSize] = {0};
747     size_t readSum = fread(buf, 1, bufSize, fp);
748     (void)fclose(fp);
749     fp = nullptr;
750     if (readSum < 1) {
751         DUMPER_HILOGE(MODULE_COMMON, "Read oom_score_adj failed.");
752         return adjLabel;
753     }
754     int value = Memory::RECLAIM_PRIORITY_UNKNOWN;
755     std::string label(buf);
756     if (label.empty()) {
757         DUMPER_HILOGE(MODULE_COMMON, "label is empty.");
758         return adjLabel;
759     }
760     if (!StrToInt(label.substr(0, label.size() - 1), value)) {
761         DUMPER_HILOGE(MODULE_COMMON, "StrToInt failed.");
762         return adjLabel;
763     }
764     adjLabel = Memory::GetReclaimPriorityString(value);
765     return adjLabel;
766 }
767 #endif
768 
GetPids()769 bool MemoryInfo::GetPids()
770 {
771     bool success = DumpCommonUtils::GetUserPids(pids_);
772     if (!success) {
773         DUMPER_HILOGE(MODULE_SERVICE, "GetPids error");
774     }
775     return success;
776 }
777 
GetVss(const int32_t & pid)778 uint64_t MemoryInfo::GetVss(const int32_t &pid)
779 {
780     string path = "/proc/" + to_string(pid) + "/statm";
781     uint64_t res = 0;
782     bool ret = FileUtils::GetInstance().LoadStringFromProcCb(path, true, true, [&](const string& line) -> void {
783         if (!line.empty()) {
784             uint64_t tempValue = 0;
785             int retScanf = sscanf_s(line.c_str(), "%llu^*", &tempValue);
786             if (retScanf != -1) {
787                 res = tempValue * VSS_BIT;
788             } else {
789                 DUMPER_HILOGE(MODULE_SERVICE, "GetVss error! pid = %{public}d", pid);
790             }
791         }
792     });
793     if (!ret) {
794         return 0;
795     }
796     return res;
797 }
798 
GetGraphicsMemory(int32_t pid,MemInfoData::GraphicsMemory & graphicsMemory,GraphicType graphicType)799 bool MemoryInfo::GetGraphicsMemory(int32_t pid, MemInfoData::GraphicsMemory &graphicsMemory, GraphicType graphicType)
800 {
801     DUMPER_HILOGD(MODULE_SERVICE, "GetGraphicUsage start, pid:%{public}d", pid);
802     std::shared_ptr<UCollectUtil::GraphicMemoryCollector> collector = UCollectUtil::GraphicMemoryCollector::Create();
803     CollectResult<int32_t> data;
804     data = collector->GetGraphicUsage(pid, graphicType, true);
805     if (data.retCode != UCollect::UcError::SUCCESS) {
806         DUMPER_HILOGE(MODULE_SERVICE, "collect progress GL or Graph error, ret:%{public}d", data.retCode);
807         return false;
808     }
809     DUMPER_HILOGD(MODULE_SERVICE, "GetGraphicUsage end, pid:%{public}d", pid);
810     if (graphicType == GraphicType::GL) {
811         graphicsMemory.gl = static_cast<uint64_t>(data.data);
812     } else if (graphicType == GraphicType::GRAPH) {
813         graphicsMemory.graph = static_cast<uint64_t>(data.data);
814     } else {
815         DUMPER_HILOGE(MODULE_SERVICE, "graphic type is not support.");
816         return false;
817     }
818     return true;
819 }
820 
GetMemByProcessPid(const int32_t & pid,MemInfoData::MemUsage & usage)821 bool MemoryInfo::GetMemByProcessPid(const int32_t &pid, MemInfoData::MemUsage &usage)
822 {
823     bool success = false;
824     MemInfoData::MemInfo memInfo;
825     unique_ptr<ParseSmapsRollupInfo> getSmapsRollup = make_unique<ParseSmapsRollupInfo>();
826     if (getSmapsRollup->GetMemInfo(pid, memInfo)) {
827         usage.vss = GetVss(pid);
828         usage.uss = memInfo.privateClean + memInfo.privateDirty;
829         usage.rss = memInfo.rss;
830         usage.pss = memInfo.pss;
831         usage.swapPss = memInfo.swapPss;
832         usage.name = GetProcName(pid);
833         usage.pid = pid;
834 #ifdef HIDUMPER_MEMMGR_ENABLE
835         usage.adjLabel = GetProcessAdjLabel(pid);
836 #endif
837         success = true;
838     }
839 
840     MemInfoData::GraphicsMemory graphicsMemory;
841     MemoryUtil::GetInstance().InitGraphicsMemory(graphicsMemory);
842     if (GetGraphicsMemory(pid, graphicsMemory, GraphicType::GL)) {
843         usage.gl = graphicsMemory.gl;
844         usage.uss = usage.uss + graphicsMemory.gl;
845         usage.pss = usage.pss + graphicsMemory.gl;
846         usage.rss = usage.rss + graphicsMemory.gl;
847     }
848     if (GetGraphicsMemory(pid, graphicsMemory, GraphicType::GRAPH)) {
849         usage.graph = graphicsMemory.graph;
850         usage.dma = graphicsMemory.graph;
851         usage.uss = usage.uss + graphicsMemory.graph;
852         usage.pss = usage.pss + graphicsMemory.graph;
853         usage.rss = usage.rss + graphicsMemory.graph;
854         DUMPER_HILOGD(MODULE_SERVICE, "uss:%{public}d pss:%{public}d rss:%{public}d gl:%{public}d graph:%{public}d",
855                       static_cast<int>(usage.uss), static_cast<int>(usage.pss), static_cast<int>(usage.rss),
856                       static_cast<int>(graphicsMemory.gl), static_cast<int>(graphicsMemory.graph));
857     }
858     return success;
859 }
860 
MemUsageToMatrix(const MemInfoData::MemUsage & memUsage,StringMatrix result)861 void MemoryInfo::MemUsageToMatrix(const MemInfoData::MemUsage &memUsage, StringMatrix result)
862 {
863     string pid = to_string(memUsage.pid);
864     StringUtils::GetInstance().SetWidth(PID_WIDTH_, BLANK_, true, pid);
865 
866     uint64_t pss = memUsage.pss + memUsage.swapPss;
867     string totalPss = to_string(pss) + "(" + to_string(memUsage.swapPss) + " in SwapPss) kB";
868     StringUtils::GetInstance().SetWidth(PSS_WIDTH_, BLANK_, false, totalPss);
869 
870     uint64_t vss = memUsage.vss;
871     string totalVss = AddKbUnit(vss);
872     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalVss);
873 
874     uint64_t rss = memUsage.rss;
875     string totalRss = AddKbUnit(rss);
876     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalRss);
877 
878     uint64_t uss = memUsage.uss;
879     string totalUss = AddKbUnit(uss);
880     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalUss);
881 
882     uint64_t gl = memUsage.gl;
883     string unMappedGL = AddKbUnit(gl);
884     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGL);
885 
886     uint64_t graph = memUsage.graph;
887     string unMappedGraph = AddKbUnit(graph);
888     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGraph);
889 
890     uint64_t dma = memUsage.dma;
891     string unMappedDma = AddKbUnit(dma);
892     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedDma);
893 
894     uint64_t purgSum = memUsage.purgSum;
895     string unMappedPurgSum = AddKbUnit(purgSum);
896     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgSum);
897 
898     uint64_t purgPin = memUsage.purgPin;
899     string unMappedPurgPin = AddKbUnit(purgPin);
900     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgPin);
901 
902     string name = "    " + memUsage.name;
903     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, name);
904 
905     (void)dprintf(rawParamFd_, "%s %s %s %s %s %s %s %s %s %s %s\n", pid.c_str(),
906         totalPss.c_str(), totalVss.c_str(), totalRss.c_str(), totalUss.c_str(),
907         unMappedGL.c_str(), unMappedGraph.c_str(), unMappedDma.c_str(), unMappedPurgSum.c_str(),
908         unMappedPurgPin.c_str(), name.c_str());
909 }
910 
AddMemByProcessTitle(StringMatrix result,string sortType)911 void MemoryInfo::AddMemByProcessTitle(StringMatrix result, string sortType)
912 {
913     string processTitle = "Total Memory Usage by " + sortType + ":";
914     (void)dprintf(rawParamFd_, "%s\n", processTitle.c_str());
915 
916     string pid = "PID";
917     StringUtils::GetInstance().SetWidth(PID_WIDTH_, BLANK_, true, pid);
918 
919     string totalPss = "Total Pss(xxx in SwapPss)";
920     StringUtils::GetInstance().SetWidth(PSS_WIDTH_, BLANK_, false, totalPss);
921 
922     string totalVss = "Total Vss";
923     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalVss);
924 
925     string totalRss = "Total Rss";
926     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalRss);
927 
928     string totalUss = "Total Uss";
929     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, totalUss);
930 
931     string unMappedGL = MemoryFilter::GetInstance().GL_OUT_LABEL;
932     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGL);
933 
934     string unMappedGraph = MemoryFilter::GetInstance().GRAPH_OUT_LABEL;
935     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedGraph);
936 
937     string unMappedDma = MemoryFilter::GetInstance().DMA_OUT_LABEL;
938     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedDma);
939 
940     string unMappedPurgSum = MemoryFilter::GetInstance().PURGSUM_OUT_LABEL;
941     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgSum);
942 
943     string unMappedPurgPin = MemoryFilter::GetInstance().PURGPIN_OUT_LABEL;
944     StringUtils::GetInstance().SetWidth(KB_WIDTH_, BLANK_, false, unMappedPurgPin);
945 
946     string name = "    Name";
947     StringUtils::GetInstance().SetWidth(NAME_WIDTH_, BLANK_, true, name);
948 
949     (void)dprintf(rawParamFd_, "%s %s %s %s %s %s %s %s %s %s %s\n", pid.c_str(),
950         totalPss.c_str(), totalVss.c_str(), totalRss.c_str(), totalUss.c_str(),
951         unMappedGL.c_str(), unMappedGraph.c_str(), unMappedDma.c_str(), unMappedPurgSum.c_str(),
952         unMappedPurgPin.c_str(), name.c_str());
953 }
954 
GetMemoryInfoNoPid(int fd,StringMatrix result)955 DumpStatus MemoryInfo::GetMemoryInfoNoPid(int fd, StringMatrix result)
956 {
957     std::lock_guard<std::mutex> lock(mutex_);
958     rawParamFd_ = fd;
959     (void)dprintf(rawParamFd_, "%s\n", MEMORY_LINE.c_str());
960     if (!isReady_) {
961         memUsages_.clear();
962         pids_.clear();
963         totalGL_ = 0;
964         totalGraph_ = 0;
965         AddMemByProcessTitle(result, "PID");
966         if (!GetPids()) {
967             return DUMP_FAIL;
968         }
969         isReady_ = true;
970     }
971 
972     if (!dumpSmapsOnStart_) {
973         dumpSmapsOnStart_ = true;
974         std::promise<GroupMap> promise;
975         fut_ = promise.get_future();
976         std::thread([promise = std::move(promise), this]() mutable {
977             GroupMap groupMap;
978             std::vector<int32_t> pids(this->pids_);
979             for (auto pid : pids) {
980                 GetSmapsInfoNoPid(pid, groupMap);
981             }
982             promise.set_value(groupMap);
983             }).detach();
984     }
985     MemInfoData::MemUsage usage;
986     MemoryUtil::GetInstance().InitMemUsage(usage);
987     for (auto pid : pids_) {
988         if (GetMemByProcessPid(pid, usage)) {
989             memUsages_.push_back(usage);
990             adjMemResult_[usage.adjLabel].push_back(usage);
991             totalGL_ += usage.gl;
992             totalGraph_ += usage.graph;
993             totalDma_ += usage.dma;
994             MemUsageToMatrix(usage, result);
995         } else {
996             DUMPER_HILOGE(MODULE_SERVICE, "Get smaps_rollup error! pid = %{public}d\n", static_cast<int>(pid));
997         }
998     }
999     return DealResult(result);
1000 }
1001 
DealResult(StringMatrix result)1002 DumpStatus MemoryInfo::DealResult(StringMatrix result)
1003 {
1004     ValueMap meminfoResult;
1005     if (!GetMeminfo(meminfoResult)) {
1006         DUMPER_HILOGE(MODULE_SERVICE, "Get meminfo error\n");
1007         return DUMP_FAIL;
1008     }
1009 
1010     GetSortedMemoryInfoNoPid(result);
1011     SaveStringToFd(rawParamFd_, "\n");
1012 #ifdef HIDUMPER_MEMMGR_ENABLE
1013     GetMemoryByAdj(result);
1014 #endif
1015     SaveStringToFd(rawParamFd_, "\n");
1016 
1017     GroupMap smapsResult = fut_.get();
1018 
1019     GetPssTotal(smapsResult, result);
1020     SaveStringToFd(rawParamFd_, "\n");
1021 
1022     GetRamUsage(smapsResult, meminfoResult, result);
1023     SaveStringToFd(rawParamFd_, "\n");
1024 
1025     GetRamCategory(smapsResult, meminfoResult, result);
1026     SaveStringToFd(rawParamFd_, "\n");
1027 
1028     GetPurgTotal(meminfoResult, result);
1029 
1030     isReady_ = false;
1031     dumpSmapsOnStart_ = false;
1032     memUsages_.clear();
1033     smapsResult.clear();
1034     return DUMP_OK;
1035 }
1036 
GetSortedMemoryInfoNoPid(StringMatrix result)1037 void MemoryInfo::GetSortedMemoryInfoNoPid(StringMatrix result)
1038 {
1039     SaveStringToFd(rawParamFd_, "\n");
1040     AddMemByProcessTitle(result, "Size");
1041 
1042     std::sort(memUsages_.begin(), memUsages_.end(),
1043         [] (MemInfoData::MemUsage &left, MemInfoData::MemUsage &right) {
1044         if (right.pss + right.swapPss != left.pss + left.swapPss) {
1045             return right.pss + right.swapPss < left.pss + left.swapPss;
1046         }
1047         if (right.vss != left.vss) {
1048             return right.vss < left.vss;
1049         }
1050         if (right.rss != left.rss) {
1051             return right.rss < left.rss;
1052         }
1053         if (right.uss != left.uss) {
1054             return right.uss < left.uss;
1055         }
1056         return right.pid < left.pid;
1057     });
1058 
1059     for (auto &memUsage : memUsages_) {
1060         MemUsageToMatrix(memUsage, result);
1061     }
1062 }
1063 
1064 #ifdef HIDUMPER_MEMMGR_ENABLE
GetMemoryByAdj(StringMatrix result)1065 void MemoryInfo::GetMemoryByAdj(StringMatrix result)
1066 {
1067     SaveStringToFd(rawParamFd_, "Total Pss by OOM adjustment:\n");
1068 
1069     vector<string> reclaimPriority_;
1070     for (auto reclaim : Memory::ReclaimPriorityMapping) {
1071         reclaimPriority_.push_back(reclaim.second);
1072     }
1073     reclaimPriority_.push_back(Memory::RECLAIM_PRIORITY_UNKNOWN_DESC);
1074 
1075     for (const auto &adjLabel : reclaimPriority_) {
1076         vector<MemInfoData::MemUsage> memUsages = adjMemResult_[adjLabel];
1077         vector<string> label;
1078         if (memUsages.size() == 0) {
1079             SaveStringToFd(rawParamFd_, adjLabel + ": " + AddKbUnit(0) + "\n");
1080             continue;
1081         }
1082         uint64_t totalPss = accumulate(memUsages.begin(), memUsages.end(), (uint64_t)0,
1083         [] (uint64_t a, MemInfoData::MemUsage &b) {
1084             return a + b.pss + b.swapPss;
1085         });
1086         SaveStringToFd(rawParamFd_, adjLabel + ": " + AddKbUnit(totalPss) + "\n");
1087 
1088         std::sort(memUsages.begin(), memUsages.end(),
1089             [] (MemInfoData::MemUsage &left, MemInfoData::MemUsage &right) {
1090             return right.pss + right.swapPss < left.pss + left.swapPss;
1091         });
1092         for (const auto &memUsage : memUsages) {
1093             string name = PRE_BLANK + memUsage.name + "(pid=" + to_string(memUsage.pid) + "): ";
1094             StringUtils::GetInstance().SetWidth(NAME_AND_PID_WIDTH, BLANK_, true, name);
1095             name += AddKbUnit(memUsage.pss + memUsage.swapPss);
1096             if (memUsage.swapPss > 0) {
1097                 name += " (" + to_string(memUsage.swapPss) + " kB in SwapPss)";
1098             }
1099             SaveStringToFd(rawParamFd_, name + "\n");
1100         }
1101     }
1102 }
1103 #endif
1104 
SetPss(MemInfoData::MemInfo & meminfo,uint64_t value)1105 void MemoryInfo::SetPss(MemInfoData::MemInfo &meminfo, uint64_t value)
1106 {
1107     meminfo.pss += value;
1108 }
1109 
SetSharedClean(MemInfoData::MemInfo & meminfo,uint64_t value)1110 void MemoryInfo::SetSharedClean(MemInfoData::MemInfo &meminfo, uint64_t value)
1111 {
1112     meminfo.sharedClean += value;
1113 }
1114 
SetSharedDirty(MemInfoData::MemInfo & meminfo,uint64_t value)1115 void MemoryInfo::SetSharedDirty(MemInfoData::MemInfo &meminfo, uint64_t value)
1116 {
1117     meminfo.sharedDirty += value;
1118 }
1119 
SetPrivateClean(MemInfoData::MemInfo & meminfo,uint64_t value)1120 void MemoryInfo::SetPrivateClean(MemInfoData::MemInfo &meminfo, uint64_t value)
1121 {
1122     meminfo.privateClean += value;
1123 }
1124 
SetPrivateDirty(MemInfoData::MemInfo & meminfo,uint64_t value)1125 void MemoryInfo::SetPrivateDirty(MemInfoData::MemInfo &meminfo, uint64_t value)
1126 {
1127     meminfo.privateDirty += value;
1128 }
1129 
SetSwap(MemInfoData::MemInfo & meminfo,uint64_t value)1130 void MemoryInfo::SetSwap(MemInfoData::MemInfo &meminfo, uint64_t value)
1131 {
1132     meminfo.swap += value;
1133 }
1134 
SetSwapPss(MemInfoData::MemInfo & meminfo,uint64_t value)1135 void MemoryInfo::SetSwapPss(MemInfoData::MemInfo &meminfo, uint64_t value)
1136 {
1137     meminfo.swapPss += value;
1138 }
SetHeapSize(MemInfoData::MemInfo & meminfo,uint64_t value)1139 void MemoryInfo::SetHeapSize(MemInfoData::MemInfo &meminfo, uint64_t value)
1140 {
1141     meminfo.heapSize += value;
1142 }
1143 
SetHeapAlloc(MemInfoData::MemInfo & meminfo,uint64_t value)1144 void MemoryInfo::SetHeapAlloc(MemInfoData::MemInfo &meminfo, uint64_t value)
1145 {
1146     meminfo.heapAlloc += value;
1147 }
1148 
SetHeapFree(MemInfoData::MemInfo & meminfo,uint64_t value)1149 void MemoryInfo::SetHeapFree(MemInfoData::MemInfo &meminfo, uint64_t value)
1150 {
1151     meminfo.heapFree += value;
1152 }
1153 } // namespace HiviewDFX
1154 } // namespace OHOS
1155