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