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