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 }