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_TYPE_STRING_LEN = 16;
25 constexpr uint32_t PIXELMAP_INFO_STRING_LEN = 32;
26 constexpr uint32_t MEM_PID_STRING_LEN = 8;
27 constexpr uint32_t MEM_WID_STRING_LEN = 20;
28 constexpr uint32_t MEM_UID_STRING_LEN = 8;
29 constexpr uint32_t MEM_SURNODE_STRING_LEN = 40;
30 constexpr uint32_t MEM_FRAME_STRING_LEN = 35;
31 constexpr uint32_t MEM_NODEID_STRING_LEN = 20;
32 }
33
MemoryNodeOfPid(size_t size,NodeId id)34 MemoryNodeOfPid::MemoryNodeOfPid(size_t size, NodeId id) : nodeSize_(size), nodeId_(id) {}
35
GetMemSize()36 size_t MemoryNodeOfPid::GetMemSize()
37 {
38 return nodeSize_;
39 }
40
operator ==(const MemoryNodeOfPid & other)41 bool MemoryNodeOfPid::operator==(const MemoryNodeOfPid& other)
42 {
43 return nodeId_ == other.nodeId_;
44 }
45
Instance()46 MemoryTrack& MemoryTrack::Instance()
47 {
48 static MemoryTrack instance;
49 return instance;
50 }
51
AddNodeRecord(const NodeId id,const MemoryInfo & info)52 void MemoryTrack::AddNodeRecord(const NodeId id, const MemoryInfo& info)
53 {
54 std::lock_guard<std::mutex> lock(mutex_);
55 memNodeMap_.emplace(id, info);
56 MemoryNodeOfPid nodeInfoOfPid(info.size, id);
57 memNodeOfPidMap_[info.pid].push_back(nodeInfoOfPid);
58 }
59
RemoveNodeFromMap(const NodeId id,pid_t & pid,size_t & size)60 bool MemoryTrack::RemoveNodeFromMap(const NodeId id, pid_t& pid, size_t& size)
61 {
62 auto itr = memNodeMap_.find(id);
63 if (itr == memNodeMap_.end()) {
64 RS_LOGD("MemoryTrack::RemoveNodeFromMap no this nodeId = %{public}" PRIu64, id);
65 return false;
66 }
67 pid = memNodeMap_[id].pid;
68 size = memNodeMap_[id].size;
69 memNodeMap_.erase(itr);
70 return true;
71 }
72
RemoveNodeOfPidFromMap(const pid_t pid,const size_t size,const NodeId id)73 void MemoryTrack::RemoveNodeOfPidFromMap(const pid_t pid, const size_t size, const NodeId id)
74 {
75 if (memNodeOfPidMap_.find(pid) == memNodeOfPidMap_.end()) {
76 RS_LOGW("MemoryTrack::RemoveNodeOfPidFromMap no this nodeId = %{public}" PRIu64, id);
77 return;
78 }
79 MemoryNodeOfPid nodeInfoOfPid = {size, id};
80 auto itr = std::find(memNodeOfPidMap_[pid].begin(), memNodeOfPidMap_[pid].end(), nodeInfoOfPid);
81 if (itr != memNodeOfPidMap_[pid].end()) {
82 memNodeOfPidMap_[pid].erase(itr);
83 }
84 }
85
RemoveNodeRecord(const NodeId id)86 void MemoryTrack::RemoveNodeRecord(const NodeId id)
87 {
88 std::lock_guard<std::mutex> lock(mutex_);
89 pid_t pid = 0;
90 size_t size = 0;
91 bool isSuccess = RemoveNodeFromMap(id, pid, size);
92 if (!isSuccess) {
93 return;
94 }
95 RemoveNodeOfPidFromMap(pid, size, id);
96 }
97
CountRSMemory(const pid_t pid)98 MemoryGraphic MemoryTrack::CountRSMemory(const pid_t pid)
99 {
100 std::lock_guard<std::mutex> lock(mutex_);
101 MemoryGraphic memoryGraphic;
102 auto itr = memNodeOfPidMap_.find(pid);
103 if (itr == memNodeOfPidMap_.end()) {
104 return memoryGraphic;
105 }
106 auto nodeInfoOfPid = memNodeOfPidMap_[pid];
107 if (nodeInfoOfPid.empty()) {
108 memNodeOfPidMap_.erase(pid);
109 } else {
110 int totalMemSize = 0;
111 std::for_each(nodeInfoOfPid.begin(), nodeInfoOfPid.end(), [&totalMemSize](MemoryNodeOfPid& info) {
112 totalMemSize += info.GetMemSize();
113 });
114
115 for (auto it = memPicRecord_.begin(); it != memPicRecord_.end(); it++) {
116 pid_t picPid = it->second.pid;
117 if (pid == picPid) {
118 totalMemSize += static_cast<int>(it->second.size);
119 }
120 }
121 memoryGraphic.SetPid(pid);
122 memoryGraphic.SetCpuMemorySize(totalMemSize);
123 }
124 return memoryGraphic;
125 }
126
GetAppMemorySizeInMB()127 float MemoryTrack::GetAppMemorySizeInMB()
128 {
129 float total = 0.f;
130 std::lock_guard<std::mutex> lock(mutex_);
131 for (auto& [_, memInfo] : memPicRecord_) {
132 total += static_cast<float>(memInfo.size);
133 }
134 return total / BYTE_CONVERT / BYTE_CONVERT / 2; // app mem account for 50%
135 }
136
DumpMemoryStatistics(DfxString & log,std::function<std::tuple<uint64_t,std::string,RectI> (uint64_t)> func)137 void MemoryTrack::DumpMemoryStatistics(DfxString& log,
138 std::function<std::tuple<uint64_t, std::string, RectI> (uint64_t)> func)
139 {
140 std::lock_guard<std::mutex> lock(mutex_);
141 DumpMemoryPicStatistics(log, func);
142 DumpMemoryNodeStatistics(log);
143 }
144
DumpMemoryNodeStatistics(DfxString & log)145 void MemoryTrack::DumpMemoryNodeStatistics(DfxString& log)
146 {
147 log.AppendFormat("\nRSRenderNode:\n");
148
149 int totalSize = 0;
150 int count = 0;
151 //calculate by byte
152 for (auto& [nodeId, info] : memNodeMap_) {
153 //total of all
154 totalSize += static_cast<int>(info.size);
155 count++;
156 }
157 log.AppendFormat("Total Node Size = %d KB (%d entries)\n", totalSize / BYTE_CONVERT, count);
158 }
159
UpdatePictureInfo(const void * addr,NodeId nodeId,pid_t pid)160 void MemoryTrack::UpdatePictureInfo(const void* addr, NodeId nodeId, pid_t pid)
161 {
162 std::lock_guard<std::mutex> lock(mutex_);
163 auto itr = memPicRecord_.find(addr);
164 if (itr != memPicRecord_.end()) {
165 itr->second.pid = pid;
166 itr->second.nid = nodeId;
167 }
168 }
169
MemoryType2String(MEMORY_TYPE type)170 const char* MemoryTrack::MemoryType2String(MEMORY_TYPE type)
171 {
172 switch (type) {
173 case MEM_PIXELMAP : {
174 return "pixelmap";
175 }
176 case MEM_SKIMAGE : {
177 return "skimage";
178 }
179 default : {
180 return "";
181 }
182 }
183 }
184
PixelMapInfo2String(MemoryInfo info)185 const std::string MemoryTrack::PixelMapInfo2String(MemoryInfo info)
186 {
187 std::string alloc_type_str = AllocatorType2String(info.allocType);
188 std::string use_cnt_str = "-1";
189 std::string is_un_map_str = "-1";
190 std::string un_map_cnt_str = "-1";
191
192 #ifdef ROSEN_OHOS
193 if (RSSystemProperties::GetDumpUIPixelmapEnabled()) {
194 auto pixelMap = info.pixelMap.lock();
195 if (pixelMap) {
196 use_cnt_str = std::to_string(pixelMap->GetUseCount());
197 is_un_map_str = std::to_string(pixelMap->IsUnMap());
198 un_map_cnt_str = std::to_string(pixelMap->GetUnMapCount());
199 }
200 }
201 #endif
202 return alloc_type_str + "," + use_cnt_str + "," + is_un_map_str + "," + un_map_cnt_str;
203 }
204
AllocatorType2String(OHOS::Media::AllocatorType type)205 const std::string MemoryTrack::AllocatorType2String(OHOS::Media::AllocatorType type)
206 {
207 switch (type) {
208 case OHOS::Media::AllocatorType::DEFAULT:
209 return "DEFAULT";
210 case OHOS::Media::AllocatorType::HEAP_ALLOC:
211 return "HEAP";
212 case OHOS::Media::AllocatorType::SHARE_MEM_ALLOC:
213 return "SHARE_MEM";
214 case OHOS::Media::AllocatorType::CUSTOM_ALLOC:
215 return "CUSTOM";
216 case OHOS::Media::AllocatorType::DMA_ALLOC:
217 return "DMA";
218 default :
219 return "UNKNOW";
220 }
221 return "UNKNOW";
222 }
223
Data2String(std::string data,uint32_t tagetNumber)224 static std::string Data2String(std::string data, uint32_t tagetNumber)
225 {
226 if (data.length() < tagetNumber) {
227 return std::string(tagetNumber - data.length(), ' ') + data;
228 } else {
229 return data;
230 }
231 }
232
GenerateDumpTitle()233 std::string MemoryTrack::GenerateDumpTitle()
234 {
235 std::string size_title = Data2String("Size", MEM_SIZE_STRING_LEN);
236 std::string type_title = Data2String("Type", MEM_TYPE_STRING_LEN);
237 std::string pixelmap_info_title = Data2String("Type,UseCnt,IsUnMap,UnMapCnt", PIXELMAP_INFO_STRING_LEN);
238 std::string pid_title = Data2String("Pid", MEM_PID_STRING_LEN);
239 std::string wid_title = Data2String("Wid", MEM_WID_STRING_LEN);
240 std::string uid_title = Data2String("Uid", MEM_UID_STRING_LEN);
241 std::string surfaceNode_title = Data2String("SurfaceName", MEM_SURNODE_STRING_LEN);
242 std::string frame_title = Data2String("Frame", MEM_FRAME_STRING_LEN);
243 std::string nid_title = Data2String("NodeId", MEM_NODEID_STRING_LEN);
244 return size_title + "\t" + type_title + "\t" + pixelmap_info_title + "\t" + pid_title + "\t" + wid_title + "\t" +
245 uid_title + "\t" + surfaceNode_title + "\t" + frame_title + nid_title;
246 }
247
GenerateDetail(MemoryInfo info,uint64_t wId,std::string & wName,RectI & nFrame)248 std::string MemoryTrack::GenerateDetail(MemoryInfo info, uint64_t wId, std::string& wName, RectI& nFrame)
249 {
250 std::string size_str = Data2String(std::to_string(info.size), MEM_SIZE_STRING_LEN);
251 std::string type_str = Data2String(MemoryType2String(info.type), MEM_TYPE_STRING_LEN);
252 std::string pixelmap_info_str = Data2String(PixelMapInfo2String(info), PIXELMAP_INFO_STRING_LEN);
253 std::string pid_str = Data2String(std::to_string(ExtractPid(info.nid)), MEM_PID_STRING_LEN);
254 std::string wid_str = Data2String(std::to_string(wId), MEM_WID_STRING_LEN);
255 std::string uid_str = Data2String(std::to_string(info.uid), MEM_UID_STRING_LEN);
256 std::string wname_str = Data2String(wName, MEM_SURNODE_STRING_LEN);
257 std::string frame_str = Data2String(nFrame.ToString(), MEM_FRAME_STRING_LEN);
258 std::string nid_str = Data2String(std::to_string(info.nid), MEM_NODEID_STRING_LEN);
259 return size_str + "\t" + type_str + "\t" + pixelmap_info_str + "\t" + pid_str + "\t" + wid_str + "\t" +
260 uid_str + "\t" + wname_str + "\t" + frame_str + nid_str;
261 }
262
DumpMemoryPicStatistics(DfxString & log,std::function<std::tuple<uint64_t,std::string,RectI> (uint64_t)> func)263 void MemoryTrack::DumpMemoryPicStatistics(DfxString& log,
264 std::function<std::tuple<uint64_t, std::string, RectI> (uint64_t)> func)
265 {
266 log.AppendFormat("RSImageCache:\n");
267 log.AppendFormat("%s:\n", GenerateDumpTitle().c_str());
268
269 int arrTotal[MEM_MAX_SIZE] = {0};
270 int arrCount[MEM_MAX_SIZE] = {0};
271 int arrWithoutDMATotal[MEM_MAX_SIZE] = {0};
272 int arrWithoutDMACount[MEM_MAX_SIZE] = {0};
273 int totalSize = 0;
274 int count = 0;
275 int totalWithoutDMASize = 0;
276 int countWithoutDMA = 0;
277 #ifdef ROSEN_OHOS
278 int totalUnMapSize = 0;
279 int totalUnMapCount = 0;
280 #endif
281 //calculate by byte
282 for (auto& [addr, info] : memPicRecord_) {
283 int size = static_cast<int>(info.size / BYTE_CONVERT); // k
284 //total of type
285 arrTotal[info.type] += size;
286 arrCount[info.type]++;
287
288 //total of all
289 totalSize += size;
290 count++;
291
292 if (info.allocType != OHOS::Media::AllocatorType::DMA_ALLOC) {
293 arrWithoutDMATotal[info.type] += size;
294 arrWithoutDMACount[info.type]++;
295 totalWithoutDMASize += size;
296 countWithoutDMA++;
297 #ifdef ROSEN_OHOS
298 if (RSSystemProperties::GetDumpUIPixelmapEnabled()) {
299 auto pixelMap = info.pixelMap.lock();
300 if (pixelMap && pixelMap->IsUnMap()) {
301 totalUnMapSize += size;
302 totalUnMapCount++;
303 }
304 }
305 #endif
306 }
307
308 auto [windowId, windowName, nodeFrameRect] = func(info.nid);
309 log.AppendFormat("%s\n", GenerateDetail(info, windowId, windowName, nodeFrameRect).c_str());
310 }
311
312 for (uint32_t i = MEM_PIXELMAP; i < MEM_MAX_SIZE; i++) {
313 MEMORY_TYPE type = static_cast<MEMORY_TYPE>(i);
314 log.AppendFormat(" %s:Size = %d KB (%d entries)\n", MemoryType2String(type), arrTotal[i], arrCount[i]);
315 log.AppendFormat(" %s Without DMA:Size = %d KB (%d entries)\n",
316 MemoryType2String(type), arrWithoutDMATotal[i], arrWithoutDMACount[i]);
317 }
318 log.AppendFormat("Total Size = %d KB (%d entries)\n", totalSize, count);
319 log.AppendFormat("Total Without DMA Size = %d KB (%d entries)\n", totalWithoutDMASize, countWithoutDMA);
320 #ifdef ROSEN_OHOS
321 log.AppendFormat("Total UnMap Size = %d KB (%d entries)\n", totalUnMapSize, totalUnMapCount);
322 #endif
323 }
324
AddPictureRecord(const void * addr,MemoryInfo info)325 void MemoryTrack::AddPictureRecord(const void* addr, MemoryInfo info)
326 {
327 std::lock_guard<std::mutex> lock(mutex_);
328 memPicRecord_.emplace(addr, info);
329 }
330
RemovePictureRecord(const void * addr)331 void MemoryTrack::RemovePictureRecord(const void* addr)
332 {
333 std::lock_guard<std::mutex> lock(mutex_);
334 memPicRecord_.erase(addr);
335 }
336
337 }
338 }