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