• 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 namespace OHOS {
19 namespace Rosen {
20 namespace {
21 constexpr uint32_t MEM_MAX_SIZE = 2;
22 constexpr uint32_t MEM_SIZE_STRING_LEN = 10;
23 constexpr uint32_t MEM_TYPE_STRING_LEN = 16;
24 constexpr uint32_t MEM_PID_STRING_LEN = 8;
25 constexpr uint32_t MEM_WID_STRING_LEN = 20;
26 constexpr uint32_t MEM_SURNODE_STRING_LEN = 40;
27 constexpr uint32_t MEM_FRAME_STRING_LEN = 35;
28 constexpr uint32_t MEM_NODEID_STRING_LEN = 20;
29 }
30 
MemoryNodeOfPid(size_t size,NodeId id)31 MemoryNodeOfPid::MemoryNodeOfPid(size_t size, NodeId id) : nodeSize_(size), nodeId_(id) {}
32 
GetMemSize()33 size_t MemoryNodeOfPid::GetMemSize()
34 {
35     return nodeSize_;
36 }
37 
operator ==(const MemoryNodeOfPid & other)38 bool MemoryNodeOfPid::operator==(const MemoryNodeOfPid& other)
39 {
40     return nodeId_ == other.nodeId_;
41 }
42 
Instance()43 MemoryTrack& MemoryTrack::Instance()
44 {
45     static MemoryTrack instance;
46     return instance;
47 }
48 
AddNodeRecord(const NodeId id,const MemoryInfo & info)49 void MemoryTrack::AddNodeRecord(const NodeId id, const MemoryInfo& info)
50 {
51     std::lock_guard<std::mutex> lock(mutex_);
52     memNodeMap_.emplace(id, info);
53     MemoryNodeOfPid nodeInfoOfPid(info.size, id);
54     memNodeOfPidMap_[info.pid].push_back(nodeInfoOfPid);
55 }
56 
RemoveNodeFromMap(const NodeId id,pid_t & pid,size_t & size)57 bool MemoryTrack::RemoveNodeFromMap(const NodeId id, pid_t& pid, size_t& size)
58 {
59     auto itr = memNodeMap_.find(id);
60     if (itr == memNodeMap_.end()) {
61         RS_LOGD("MemoryTrack::RemoveNodeFromMap no this nodeId = %" PRIu64, id);
62         return false;
63     }
64     pid = memNodeMap_[id].pid;
65     size = memNodeMap_[id].size;
66     memNodeMap_.erase(itr);
67     return true;
68 }
69 
RemoveNodeOfPidFromMap(const pid_t pid,const size_t size,const NodeId id)70 void MemoryTrack::RemoveNodeOfPidFromMap(const pid_t pid, const size_t size, const NodeId id)
71 {
72     if (memNodeOfPidMap_.find(pid) == memNodeOfPidMap_.end()) {
73         RS_LOGW("MemoryTrack::RemoveNodeOfPidFromMap no this nodeId = %" PRIu64, id);
74         return;
75     }
76     MemoryNodeOfPid nodeInfoOfPid = {size, id};
77     auto itr = std::find(memNodeOfPidMap_[pid].begin(), memNodeOfPidMap_[pid].end(), nodeInfoOfPid);
78     if (itr != memNodeOfPidMap_[pid].end()) {
79         memNodeOfPidMap_[pid].erase(itr);
80     }
81 }
82 
RemoveNodeRecord(const NodeId id)83 void MemoryTrack::RemoveNodeRecord(const NodeId id)
84 {
85     std::lock_guard<std::mutex> lock(mutex_);
86     pid_t pid = 0;
87     size_t size = 0;
88     bool isSuccess = RemoveNodeFromMap(id, pid, size);
89     if (!isSuccess) {
90         return;
91     }
92     RemoveNodeOfPidFromMap(pid, size, id);
93 }
94 
CountRSMemory(const pid_t pid)95 MemoryGraphic MemoryTrack::CountRSMemory(const pid_t pid)
96 {
97     MemoryGraphic memoryGraphic;
98     auto itr = memNodeOfPidMap_.find(pid);
99     if (itr == memNodeOfPidMap_.end()) {
100         return memoryGraphic;
101     }
102     auto nodeInfoOfPid = memNodeOfPidMap_[pid];
103     if (nodeInfoOfPid.empty()) {
104         memNodeOfPidMap_.erase(pid);
105     } else {
106         int totalMemSize = 0;
107         std::for_each(nodeInfoOfPid.begin(), nodeInfoOfPid.end(), [&totalMemSize](MemoryNodeOfPid& info) {
108             totalMemSize += info.GetMemSize();
109         });
110 
111         for (auto it = memPicRecord_.begin(); it != memPicRecord_.end(); it++) {
112             pid_t picPid = it->second.pid;
113             if (pid == picPid) {
114                 totalMemSize += static_cast<int>(it->second.size);
115             }
116         }
117         memoryGraphic.SetPid(pid);
118         memoryGraphic.SetCpuMemorySize(totalMemSize);
119     }
120     return memoryGraphic;
121 }
122 
DumpMemoryStatistics(DfxString & log,std::function<std::tuple<uint64_t,std::string,RectI> (uint64_t)> func)123 void MemoryTrack::DumpMemoryStatistics(DfxString& log,
124     std::function<std::tuple<uint64_t, std::string, RectI> (uint64_t)> func)
125 {
126     std::lock_guard<std::mutex> lock(mutex_);
127     DumpMemoryPicStatistics(log, func);
128     DumpMemoryNodeStatistics(log);
129 }
130 
DumpMemoryNodeStatistics(DfxString & log)131 void MemoryTrack::DumpMemoryNodeStatistics(DfxString& log)
132 {
133     log.AppendFormat("\nRSRenderNode:\n");
134 
135     int totalSize = 0;
136     int count = 0;
137     //calculate by byte
138     for (auto& [nodeId, info] : memNodeMap_) {
139         //total of all
140         totalSize += static_cast<int>(info.size);
141         count++;
142     }
143     log.AppendFormat("Total Node Size = %d KB (%d entries)\n", totalSize / BYTE_CONVERT, count);
144 }
145 
UpdatePictureInfo(const void * addr,NodeId nodeId,pid_t pid)146 void MemoryTrack::UpdatePictureInfo(const void* addr, NodeId nodeId, pid_t pid)
147 {
148     std::lock_guard<std::mutex> lock(mutex_);
149     auto itr = memPicRecord_.find(addr);
150     if (itr != memPicRecord_.end()) {
151         itr->second.pid = pid;
152         itr->second.nid = nodeId;
153     }
154 }
155 
MemoryType2String(MEMORY_TYPE type)156 const char* MemoryTrack::MemoryType2String(MEMORY_TYPE type)
157 {
158     switch (type) {
159         case MEM_PIXELMAP : {
160             return "pixelmap";
161         }
162         case MEM_SKIMAGE : {
163             return "skimage";
164         }
165         default : {
166             return "";
167         }
168     }
169 }
170 
Data2String(std::string data,uint32_t tagetNumber)171 static std::string Data2String(std::string data, uint32_t tagetNumber)
172 {
173     if (data.length() < tagetNumber) {
174         return std::string(tagetNumber - data.length(), ' ') + data;
175     } else {
176         return data;
177     }
178 }
179 
GenerateDumpTitle()180 std::string MemoryTrack::GenerateDumpTitle()
181 {
182     std::string size_title = Data2String("Size", MEM_SIZE_STRING_LEN);
183     std::string type_title = Data2String("Type", MEM_TYPE_STRING_LEN);
184     std::string pid_title = Data2String("Pid", MEM_PID_STRING_LEN);
185     std::string wid_title = Data2String("Wid", MEM_WID_STRING_LEN);
186     std::string surfaceNode_title = Data2String("SurfaceName", MEM_SURNODE_STRING_LEN);
187     std::string frame_title = Data2String("Frame", MEM_FRAME_STRING_LEN);
188     std::string nid_title = Data2String("NodeId", MEM_NODEID_STRING_LEN);
189     return size_title + "\t" + type_title + "\t" + pid_title + "\t" + wid_title + "\t" +
190         surfaceNode_title + "\t" + frame_title + nid_title;
191 }
192 
GenerateDetail(MemoryInfo info,uint64_t wId,std::string & wName,RectI & nFrame)193 std::string MemoryTrack::GenerateDetail(MemoryInfo info, uint64_t wId, std::string& wName, RectI& nFrame)
194 {
195     std::string size_str = Data2String(std::to_string(info.size), MEM_SIZE_STRING_LEN);
196     std::string type_str = Data2String(MemoryType2String(info.type), MEM_TYPE_STRING_LEN);
197     std::string pid_str = Data2String(std::to_string(ExtractPid(info.nid)), MEM_PID_STRING_LEN);
198     std::string wid_str = Data2String(std::to_string(wId), MEM_WID_STRING_LEN);
199     std::string wname_str = Data2String(wName, MEM_SURNODE_STRING_LEN);
200     std::string frame_str = Data2String(nFrame.ToString(), MEM_FRAME_STRING_LEN);
201     std::string nid_str = Data2String(std::to_string(info.nid), MEM_NODEID_STRING_LEN);
202     return size_str + "\t" + type_str + "\t" + pid_str + "\t" + wid_str + "\t" + wname_str + "\t" + frame_str + nid_str;
203 }
204 
DumpMemoryPicStatistics(DfxString & log,std::function<std::tuple<uint64_t,std::string,RectI> (uint64_t)> func)205 void MemoryTrack::DumpMemoryPicStatistics(DfxString& log,
206     std::function<std::tuple<uint64_t, std::string, RectI> (uint64_t)> func)
207 {
208     log.AppendFormat("RSImageCache:\n");
209     log.AppendFormat("%s:\n", GenerateDumpTitle().c_str());
210 
211     int arrTotal[MEM_MAX_SIZE] = {0};
212     int arrCount[MEM_MAX_SIZE] = {0};
213     int totalSize = 0;
214     int count = 0;
215     //calculate by byte
216     for (auto& [addr, info] : memPicRecord_) {
217         int size = static_cast<int>(info.size / BYTE_CONVERT); // k
218         //total of type
219         arrTotal[info.type] += size;
220         arrCount[info.type]++;
221 
222         //total of all
223         totalSize += size;
224         count++;
225         auto [windowId, windowName, nodeFrameRect] = func(info.nid);
226         log.AppendFormat("%s\n", GenerateDetail(info, windowId, windowName, nodeFrameRect).c_str());
227     }
228 
229     for (uint32_t i = MEM_PIXELMAP; i < MEM_MAX_SIZE; i++) {
230         MEMORY_TYPE type = static_cast<MEMORY_TYPE>(i);
231         log.AppendFormat("  %s:Size = %d KB (%d entries)\n", MemoryType2String(type), arrTotal[i], arrCount[i]);
232     }
233     log.AppendFormat("Total Size = %d KB (%d entries)\n", totalSize, count);
234 }
235 
AddPictureRecord(const void * addr,MemoryInfo info)236 void MemoryTrack::AddPictureRecord(const void* addr, MemoryInfo info)
237 {
238     std::lock_guard<std::mutex> lock(mutex_);
239     memPicRecord_.emplace(addr, info);
240 }
241 
RemovePictureRecord(const void * addr)242 void MemoryTrack::RemovePictureRecord(const void* addr)
243 {
244     std::lock_guard<std::mutex> lock(mutex_);
245     memPicRecord_.erase(addr);
246 }
247 
248 }
249 }