• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "memory/rs_memory_track.h"
16 
17 #include "platform/common/rs_log.h"
18 #include "platform/common/rs_system_properties.h"
19 namespace OHOS {
20 namespace Rosen {
21 namespace {
22 constexpr uint32_t MEM_MAX_SIZE = 2;
23 constexpr uint32_t MEM_SIZE_STRING_LEN = 10;
24 constexpr uint32_t MEM_ADDR_STRING_LEN = 16;
25 constexpr uint32_t MEM_TYPE_STRING_LEN = 16;
26 constexpr uint32_t PIXELMAP_INFO_STRING_LEN = 36;
27 constexpr uint32_t MEM_PID_STRING_LEN = 8;
28 constexpr uint32_t MEM_WID_STRING_LEN = 20;
29 constexpr uint32_t MEM_UID_STRING_LEN = 8;
30 constexpr uint32_t MEM_SURNODE_STRING_LEN = 40;
31 constexpr uint32_t MEM_FRAME_STRING_LEN = 35;
32 constexpr uint32_t MEM_NODEID_STRING_LEN = 20;
33 }
34 
MemoryNodeOfPid(size_t size,NodeId id)35 MemoryNodeOfPid::MemoryNodeOfPid(size_t size, NodeId id) : nodeSize_(size), nodeId_(id) {}
36 
GetMemSize()37 size_t MemoryNodeOfPid::GetMemSize()
38 {
39     return nodeSize_;
40 }
41 
SetMemSize(size_t size)42 void MemoryNodeOfPid::SetMemSize(size_t size)
43 {
44     nodeSize_ = size;
45 }
46 
operator ==(const MemoryNodeOfPid & other)47 bool MemoryNodeOfPid::operator==(const MemoryNodeOfPid& other)
48 {
49     return nodeId_ == other.nodeId_;
50 }
51 
Instance()52 MemoryTrack& MemoryTrack::Instance()
53 {
54     static MemoryTrack instance;
55     return instance;
56 }
57 
AddNodeRecord(const NodeId id,const MemoryInfo & info)58 void MemoryTrack::AddNodeRecord(const NodeId id, const MemoryInfo& info)
59 {
60     std::lock_guard<std::mutex> lock(mutex_);
61     MemoryNodeOfPid nodeInfoOfPid(info.size, id);
62     auto itr = memNodeMap_.find(id);
63     if (itr == memNodeMap_.end()) {
64         memNodeMap_.emplace(id, info);
65         memNodeOfPidMap_[info.pid].push_back(nodeInfoOfPid);
66         return;
67     } else if (info.size > itr->second.size) {
68         nodeInfoOfPid.SetMemSize(itr->second.size);
69         itr->second.size = info.size;
70     } else {
71         return;
72     }
73 
74     if (memNodeOfPidMap_.find(info.pid) != memNodeOfPidMap_.end()) {
75         auto pidMemItr = std::find(memNodeOfPidMap_[info.pid].begin(),
76             memNodeOfPidMap_[info.pid].end(), nodeInfoOfPid);
77         if (pidMemItr != memNodeOfPidMap_[info.pid].end()) {
78             pidMemItr->SetMemSize(info.size);
79         } else {
80             nodeInfoOfPid.SetMemSize(info.size);
81             memNodeOfPidMap_[info.pid].push_back(nodeInfoOfPid);
82         }
83     } else {
84         nodeInfoOfPid.SetMemSize(info.size);
85         memNodeOfPidMap_[info.pid].push_back(nodeInfoOfPid);
86     }
87 }
88 
RemoveNodeFromMap(const NodeId id,pid_t & pid,size_t & size)89 bool MemoryTrack::RemoveNodeFromMap(const NodeId id, pid_t& pid, size_t& size)
90 {
91     auto itr = memNodeMap_.find(id);
92     if (itr == memNodeMap_.end()) {
93         RS_LOGD("MemoryTrack::RemoveNodeFromMap no this nodeId = %{public}" PRIu64, id);
94         return false;
95     }
96     pid = memNodeMap_[id].pid;
97     size = memNodeMap_[id].size;
98     memNodeMap_.erase(itr);
99     return true;
100 }
101 
RemoveNodeOfPidFromMap(const pid_t pid,const size_t size,const NodeId id)102 void MemoryTrack::RemoveNodeOfPidFromMap(const pid_t pid, const size_t size, const NodeId id)
103 {
104     if (memNodeOfPidMap_.find(pid) == memNodeOfPidMap_.end()) {
105         RS_LOGW("MemoryTrack::RemoveNodeOfPidFromMap no this nodeId = %{public}" PRIu64, id);
106         return;
107     }
108     MemoryNodeOfPid nodeInfoOfPid = {size, id};
109     auto itr = std::find(memNodeOfPidMap_[pid].begin(), memNodeOfPidMap_[pid].end(), nodeInfoOfPid);
110     if (itr != memNodeOfPidMap_[pid].end()) {
111         memNodeOfPidMap_[pid].erase(itr);
112     }
113 }
114 
RemoveNodeRecord(const NodeId id)115 void MemoryTrack::RemoveNodeRecord(const NodeId id)
116 {
117     std::lock_guard<std::mutex> lock(mutex_);
118     pid_t pid = 0;
119     size_t size = 0;
120     bool isSuccess = RemoveNodeFromMap(id, pid, size);
121     if (!isSuccess) {
122         return;
123     }
124     RemoveNodeOfPidFromMap(pid, size, id);
125 }
126 
CountRSMemory(const pid_t pid)127 MemoryGraphic MemoryTrack::CountRSMemory(const pid_t pid)
128 {
129     std::lock_guard<std::mutex> lock(mutex_);
130     MemoryGraphic memoryGraphic;
131     auto itr = memNodeOfPidMap_.find(pid);
132     if (itr == memNodeOfPidMap_.end()) {
133         return memoryGraphic;
134     }
135     auto nodeInfoOfPid = memNodeOfPidMap_[pid];
136     if (nodeInfoOfPid.empty()) {
137         memNodeOfPidMap_.erase(pid);
138     } else {
139         uint64_t totalMemSize = 0;
140         std::for_each(nodeInfoOfPid.begin(), nodeInfoOfPid.end(), [&totalMemSize](MemoryNodeOfPid& info) {
141             totalMemSize += static_cast<uint64_t>(info.GetMemSize());
142         });
143 
144         for (auto it = memPicRecord_.begin(); it != memPicRecord_.end(); it++) {
145             pid_t picPid = it->second.pid;
146             if (pid == picPid) {
147                 totalMemSize += static_cast<int>(it->second.size);
148             }
149         }
150         memoryGraphic.SetPid(pid);
151         memoryGraphic.SetCpuMemorySize(totalMemSize);
152     }
153     return memoryGraphic;
154 }
155 
GetAppMemorySizeInMB()156 float MemoryTrack::GetAppMemorySizeInMB()
157 {
158     float total = 0.f;
159     std::lock_guard<std::mutex> lock(mutex_);
160     for (auto& [_, memInfo] : memPicRecord_) {
161         total += static_cast<float>(memInfo.size);
162     }
163     return total / BYTE_CONVERT / BYTE_CONVERT / 2; // app mem account for 50%
164 }
165 
DumpMemoryStatistics(DfxString & log,std::function<std::tuple<uint64_t,std::string,RectI,bool> (uint64_t)> func)166 void MemoryTrack::DumpMemoryStatistics(DfxString& log,
167     std::function<std::tuple<uint64_t, std::string, RectI, bool> (uint64_t)> func)
168 {
169     std::vector<MemoryInfo> memPicRecord;
170     {
171         std::lock_guard<std::mutex> lock(mutex_);
172         for (auto& [addr, info] : memPicRecord_) {
173             memPicRecord.push_back(info);
174         }
175     }
176     // dump without mutex to avoid dead lock
177     // because it may free pixelmap after fetch shard_ptr(use_count = 1) from pixelmap's weak_ptr
178     DumpMemoryPicStatistics(log, func, memPicRecord);
179     {
180         std::lock_guard<std::mutex> lock(mutex_);
181         DumpMemoryNodeStatistics(log);
182     }
183 }
184 
DumpMemoryNodeStatistics(DfxString & log)185 void MemoryTrack::DumpMemoryNodeStatistics(DfxString& log)
186 {
187     log.AppendFormat("\nRSRenderNode:\n");
188 
189     uint64_t totalSize = 0;
190     int count = 0;
191     //calculate by byte
192     for (auto& [nodeId, info] : memNodeMap_) {
193         //total of all
194         totalSize += static_cast<uint64_t>(info.size);
195         count++;
196     }
197     log.AppendFormat("Total Node Size = %d KB (%d entries)\n", totalSize / BYTE_CONVERT, count);
198 }
199 
UpdatePictureInfo(const void * addr,NodeId nodeId,pid_t pid)200 void MemoryTrack::UpdatePictureInfo(const void* addr, NodeId nodeId, pid_t pid)
201 {
202     std::lock_guard<std::mutex> lock(mutex_);
203     auto itr = memPicRecord_.find(addr);
204     if (itr != memPicRecord_.end()) {
205         itr->second.pid = pid;
206         itr->second.nid = nodeId;
207     }
208 }
209 
MemoryType2String(MEMORY_TYPE type)210 const char* MemoryTrack::MemoryType2String(MEMORY_TYPE type)
211 {
212     switch (type) {
213         case MEM_PIXELMAP : {
214             return "pixelmap";
215         }
216         case MEM_SKIMAGE : {
217             return "skimage";
218         }
219         default : {
220             return "";
221         }
222     }
223 }
224 
PixelMapInfo2String(MemoryInfo info)225 const std::string MemoryTrack::PixelMapInfo2String(MemoryInfo info)
226 {
227     std::string alloc_type_str = AllocatorType2String(info.allocType);
228     std::string pixelformat_str = "UNDEFINED";
229 #ifdef ROSEN_OHOS
230     pixelformat_str = PixelFormat2String(info.pixelMapFormat);
231 #endif
232     return alloc_type_str + "," + pixelformat_str;
233 }
234 
235 #ifdef ROSEN_OHOS
PixelFormat2String(OHOS::Media::PixelFormat type)236 const std::string MemoryTrack::PixelFormat2String(OHOS::Media::PixelFormat type)
237 {
238     // sync with foundation/multimedia/image_framework/interfaces/innerkits/include/image_type.h
239     switch (type) {
240         case OHOS::Media::PixelFormat::ARGB_8888:
241             return "ARGB_8888";
242         case OHOS::Media::PixelFormat::RGB_565:
243             return "RGB_565";
244         case OHOS::Media::PixelFormat::RGBA_8888:
245             return "RGBA_8888";
246         case OHOS::Media::PixelFormat::BGRA_8888:
247             return "BGRA_8888";
248         case OHOS::Media::PixelFormat::RGB_888:
249             return "RGB_888";
250         case OHOS::Media::PixelFormat::ALPHA_8:
251             return "ALPHA_8";
252         case OHOS::Media::PixelFormat::RGBA_F16:
253             return "RGBA_F16";
254         case OHOS::Media::PixelFormat::NV21:
255             return "NV21";
256         case OHOS::Media::PixelFormat::NV12:
257             return "NV12";
258         case OHOS::Media::PixelFormat::RGBA_1010102:
259             return "RGBA_1010102";
260         case OHOS::Media::PixelFormat::YCBCR_P010:
261             return "YCBCR_P010";
262         case OHOS::Media::PixelFormat::YCRCB_P010:
263             return "YCRCB_P010";
264         case OHOS::Media::PixelFormat::RGBA_U16:
265             return "RGBA_U16";
266         case OHOS::Media::PixelFormat::YUV_400:
267             return "YUV_400";
268         case OHOS::Media::PixelFormat::CMYK:
269             return "CMYK";
270         case OHOS::Media::PixelFormat::ASTC_4x4:
271             return "ASTC_4x4";
272         case OHOS::Media::PixelFormat::ASTC_6x6:
273             return "ASTC_6x6";
274         case OHOS::Media::PixelFormat::ASTC_8x8:
275             return "ASTC_8x8";
276         default :
277             return std::to_string(static_cast<int32_t>(type));
278     }
279     return "UNKNOW";
280 }
281 #endif
282 
AllocatorType2String(OHOS::Media::AllocatorType type)283 const std::string MemoryTrack::AllocatorType2String(OHOS::Media::AllocatorType type)
284 {
285     switch (type) {
286         case OHOS::Media::AllocatorType::DEFAULT:
287             return "DEFAULT";
288         case OHOS::Media::AllocatorType::HEAP_ALLOC:
289             return "HEAP";
290         case OHOS::Media::AllocatorType::SHARE_MEM_ALLOC:
291             return "SHARE_MEM";
292         case OHOS::Media::AllocatorType::CUSTOM_ALLOC:
293             return "CUSTOM";
294         case OHOS::Media::AllocatorType::DMA_ALLOC:
295             return "DMA";
296         default :
297             return "UNKNOW";
298     }
299     return "UNKNOW";
300 }
301 
Data2String(std::string data,uint32_t tagetNumber)302 static std::string Data2String(std::string data, uint32_t tagetNumber)
303 {
304     if (data.length() < tagetNumber) {
305         return std::string(tagetNumber - data.length(), ' ') + data;
306     } else {
307         return data;
308     }
309 }
310 
GenerateDumpTitle()311 std::string MemoryTrack::GenerateDumpTitle()
312 {
313     std::string size_title = Data2String("Size", MEM_SIZE_STRING_LEN);
314     std::string type_title = Data2String("Type", MEM_TYPE_STRING_LEN);
315     std::string pixelmap_info_title = Data2String("Type,UseCnt,IsUnMap,UnMapCnt,Format", PIXELMAP_INFO_STRING_LEN);
316     std::string pid_title = Data2String("Pid", MEM_PID_STRING_LEN);
317     std::string wid_title = Data2String("Wid", MEM_WID_STRING_LEN);
318     std::string uid_title = Data2String("Uid", MEM_UID_STRING_LEN);
319     std::string surfaceNode_title = Data2String("SurfaceName", MEM_SURNODE_STRING_LEN);
320     std::string frame_title = Data2String("Frame", MEM_FRAME_STRING_LEN);
321     std::string nid_title = Data2String("NodeId", MEM_NODEID_STRING_LEN);
322     std::string addr_tile = Data2String("Addr", MEM_ADDR_STRING_LEN);
323     return size_title + "\t" + type_title + "\t" + pixelmap_info_title + "\t" + pid_title + "\t" + wid_title + "\t" +
324         uid_title + "\t" + surfaceNode_title + "\t" + frame_title + nid_title + "\t" + addr_tile;
325 }
326 
GenerateDetail(MemoryInfo info,uint64_t wId,std::string & wName,RectI & nFrame)327 std::string MemoryTrack::GenerateDetail(MemoryInfo info, uint64_t wId, std::string& wName, RectI& nFrame)
328 {
329     std::string size_str = Data2String(std::to_string(info.size), MEM_SIZE_STRING_LEN);
330     std::string type_str = Data2String(MemoryType2String(info.type), MEM_TYPE_STRING_LEN);
331     std::string pixelmap_info_str = Data2String(PixelMapInfo2String(info), PIXELMAP_INFO_STRING_LEN);
332     std::string pid_str = Data2String(std::to_string(ExtractPid(info.nid)), MEM_PID_STRING_LEN);
333     std::string wid_str = Data2String(std::to_string(wId), MEM_WID_STRING_LEN);
334     std::string uid_str = Data2String(std::to_string(info.uid), MEM_UID_STRING_LEN);
335     std::string wname_str = Data2String(wName, MEM_SURNODE_STRING_LEN);
336     std::string frame_str = Data2String(nFrame.ToString(), MEM_FRAME_STRING_LEN);
337     std::string nid_str = Data2String(std::to_string(info.nid), MEM_NODEID_STRING_LEN);
338     return size_str + "\t" + type_str + "\t" + pixelmap_info_str + "\t" + pid_str + "\t" + wid_str + "\t" +
339         uid_str + "\t" + wname_str + "\t" + frame_str + nid_str;
340 }
341 
DumpMemoryPicStatistics(DfxString & log,std::function<std::tuple<uint64_t,std::string,RectI,bool> (uint64_t)> func,const std::vector<MemoryInfo> & memPicRecord)342 void MemoryTrack::DumpMemoryPicStatistics(DfxString& log,
343     std::function<std::tuple<uint64_t, std::string, RectI, bool> (uint64_t)> func,
344     const std::vector<MemoryInfo>& memPicRecord)
345 {
346     log.AppendFormat("RSImageCache:\n");
347     log.AppendFormat("%s:\n", GenerateDumpTitle().c_str());
348 
349     int arrTotal[MEM_MAX_SIZE] = {0};
350     int arrCount[MEM_MAX_SIZE] = {0};
351     int arrWithoutDMATotal[MEM_MAX_SIZE] = {0};
352     int arrWithoutDMACount[MEM_MAX_SIZE] = {0};
353     uint64_t totalSize = 0;
354     int count = 0;
355     int totalWithoutDMASize = 0;
356     int countWithoutDMA = 0;
357     int totalNullNodeSize = 0;
358     int countNullNodes = 0;
359     int nullWithoutDMASize = 0;
360     int nullWithoutDMA = 0;
361     //calculate by byte
362     for (auto& info : memPicRecord) {
363         int size = static_cast<uint64_t>(info.size / BYTE_CONVERT); // k
364         //total of type
365         arrTotal[info.type] += size;
366         arrCount[info.type]++;
367 
368         //total of all
369         totalSize += size;
370         count++;
371 
372         if (info.allocType != OHOS::Media::AllocatorType::DMA_ALLOC) {
373             arrWithoutDMATotal[info.type] += size;
374             arrWithoutDMACount[info.type]++;
375             totalWithoutDMASize += size;
376             countWithoutDMA++;
377         }
378 
379         auto [windowId, windowName, nodeFrameRect, isNodeNull] = func(info.nid);
380         log.AppendFormat("%s", GenerateDetail(info, windowId, windowName, nodeFrameRect).c_str());
381         if (info.type == MEMORY_TYPE::MEM_PIXELMAP) {
382             log.AppendFormat("     %d\n", isNodeNull ? 1 : 0);
383             if (isNodeNull) {
384                 totalNullNodeSize += size;
385                 countNullNodes++;
386                 if (info.allocType != OHOS::Media::AllocatorType::DMA_ALLOC) {
387                     nullWithoutDMASize += size;
388                     nullWithoutDMA++;
389                 }
390             }
391         }
392     }
393 
394     for (uint32_t i = MEM_PIXELMAP; i < MEM_MAX_SIZE; i++) {
395         MEMORY_TYPE type = static_cast<MEMORY_TYPE>(i);
396         log.AppendFormat("  %s:Size = %d KB (%d entries)\n", MemoryType2String(type), arrTotal[i], arrCount[i]);
397         log.AppendFormat("  %s Without DMA:Size = %d KB (%d entries)\n",
398             MemoryType2String(type), arrWithoutDMATotal[i], arrWithoutDMACount[i]);
399     }
400     log.AppendFormat("Total Size = %d KB (%d entries)\n", totalSize, count);
401     log.AppendFormat("Total Without DMA Size = %d KB (%d entries)\n", totalWithoutDMASize, countWithoutDMA);
402     log.AppendFormat("MEM_PIXELMAP Null Nodes: Size = %d KB (%d entries)\n", totalNullNodeSize, countNullNodes);
403     log.AppendFormat("Null Nodes Without DMA: Size = %d KB (%d entries)\n", nullWithoutDMASize, nullWithoutDMA);
404 }
405 
AddPictureRecord(const void * addr,MemoryInfo info)406 void MemoryTrack::AddPictureRecord(const void* addr, MemoryInfo info)
407 {
408     std::lock_guard<std::mutex> lock(mutex_);
409     memPicRecord_.emplace(addr, info);
410 }
411 
RemovePictureRecord(const void * addr)412 void MemoryTrack::RemovePictureRecord(const void* addr)
413 {
414     std::lock_guard<std::mutex> lock(mutex_);
415     memPicRecord_.erase(addr);
416 }
417 
418 #ifdef RS_MEMORY_INFO_MANAGER
SetGlobalRootNodeStatusChangeFlag(bool flag)419 void MemoryTrack::SetGlobalRootNodeStatusChangeFlag(bool flag)
420 {
421     globalRootNodeStatusChangeFlag.store(flag);
422 }
423 
GetGlobalRootNodeStatusChangeFlag()424 bool MemoryTrack::GetGlobalRootNodeStatusChangeFlag()
425 {
426     return globalRootNodeStatusChangeFlag.load();
427 }
428 
GetNodeOnTreeStatus(const void * address)429 NODE_ON_TREE_STATUS MemoryTrack::GetNodeOnTreeStatus(const void* address)
430 {
431     std::lock_guard<std::mutex> lock(mutex_);
432 
433     auto picRecordIt = memPicRecord_.find(address);
434     if (picRecordIt == memPicRecord_.end()) {
435         return NODE_ON_TREE_STATUS::STATUS_INVALID;
436     }
437 
438     NodeId nodeId = picRecordIt->second.nid;
439     auto nodeInfoIt = memNodeMap_.find(nodeId);
440     if (nodeInfoIt == memNodeMap_.end()) {
441         return NODE_ON_TREE_STATUS::STATUS_INVALID;
442     }
443 
444     const auto& nodeInfo = nodeInfoIt->second;
445     if (nodeInfo.isOnTree && !nodeInfo.rootNodeStatusChangeFlag) {
446         return NODE_ON_TREE_STATUS::STATUS_ON_TREE;
447     } else if (nodeInfo.isOnTree) {
448         return NODE_ON_TREE_STATUS::STATUS_ON_TREE_IN_ROOT;
449     } else if (!nodeInfo.isOnTree && !nodeInfo.rootNodeStatusChangeFlag) {
450         return NODE_ON_TREE_STATUS::STATUS_OFF_TREE;
451     } else {
452         return NODE_ON_TREE_STATUS::STATUS_OFF_TREE_IN_ROOT;
453     }
454 }
455 
SetNodeOnTreeStatus(NodeId nodeId,bool rootNodeStatusChangeFlag,bool isOnTree)456 void MemoryTrack::SetNodeOnTreeStatus(NodeId nodeId, bool rootNodeStatusChangeFlag, bool isOnTree)
457 {
458     std::lock_guard<std::mutex> lock(mutex_);
459 
460     auto itr = memNodeMap_.find(nodeId);
461     if (itr == memNodeMap_.end()) {
462         return;
463     }
464     itr->second.rootNodeStatusChangeFlag = rootNodeStatusChangeFlag;
465     itr->second.isOnTree = isOnTree;
466 }
467 #endif
468 }
469 }