1 /*
2 * Copyright (c) 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
16 #include "memory/rs_memory_manager.h"
17
18 #include <malloc.h>
19 #include "include/core/SkGraphics.h"
20 #include "rs_trace.h"
21
22 #include "rs_skia_memory_tracer.h"
23 #include "memory/rs_memory_graphic.h"
24 #ifdef NEW_SKIA
25 #include "include/gpu/GrDirectContext.h"
26 #include "src/gpu/GrDirectContextPriv.h"
27 #else
28 #include "include/gpu/GrContext.h"
29 #include "src/gpu/GrContextPriv.h"
30 #endif
31
32 #include "common/rs_obj_abs_geometry.h"
33 #include "memory/rs_tag_tracker.h"
34 #ifdef NEW_RENDER_CONTEXT
35 #include "render_context/memory_handler.h"
36 #endif
37 #include "pipeline/rs_main_thread.h"
38 #include "pipeline/rs_surface_render_node.h"
39 #include "platform/common/rs_log.h"
40
41 namespace OHOS::Rosen {
42 namespace {
43 constexpr uint32_t MEMUNIT_RATE = 1024;
44 constexpr const char* MEM_RS_TYPE = "renderservice";
45 constexpr const char* MEM_CPU_TYPE = "cpu";
46 constexpr const char* MEM_GPU_TYPE = "gpu";
47 constexpr const char* MEM_JEMALLOC_TYPE = "jemalloc";
48 }
49
50 #ifndef USE_ROSEN_DRAWING
51 #ifdef NEW_SKIA
DumpMemoryUsage(DfxString & log,const GrDirectContext * grContext,std::string & type)52 void MemoryManager::DumpMemoryUsage(DfxString& log, const GrDirectContext* grContext, std::string& type)
53 #else
54 void MemoryManager::DumpMemoryUsage(DfxString& log, const GrContext* grContext, std::string& type)
55 #endif
56 {
57 if (type.empty() || type == MEM_RS_TYPE) {
58 DumpRenderServiceMemory(log);
59 }
60 if (type.empty() || type == MEM_CPU_TYPE) {
61 DumpDrawingCpuMemory(log);
62 }
63 if (type.empty() || type == MEM_GPU_TYPE) {
64 DumpDrawingGpuMemory(log, grContext);
65 }
66 if (type.empty() || type == MEM_JEMALLOC_TYPE) {
67 std::string out;
68 DumpMallocStat(out);
69 log.AppendFormat("%s\n... detail dump at hilog\n", out.c_str());
70 }
71 }
72 #else
DumpMemoryUsage(DfxString & log,const Drawing::GPUContext * gpuContext,std::string & type)73 void MemoryManager::DumpMemoryUsage(DfxString& log, const Drawing::GPUContext* gpuContext, std::string& type)
74 {
75 if (type.empty() || type == MEM_RS_TYPE) {
76 DumpRenderServiceMemory(log);
77 }
78 if (type.empty() || type == MEM_CPU_TYPE) {
79 DumpDrawingCpuMemory(log);
80 }
81 if (type.empty() || type == MEM_GPU_TYPE) {
82 DumpDrawingGpuMemory(log, gpuContext);
83 }
84 if (type.empty() || type == MEM_JEMALLOC_TYPE) {
85 std::string out;
86 DumpMallocStat(out);
87 log.AppendFormat("%s\n... detail dump at hilog\n", out.c_str());
88 }
89 }
90 #endif // USE_ROSEN_DRAWING
91
92 #ifndef USE_ROSEN_DRAWING
93 #ifdef NEW_SKIA
ReleaseAllGpuResource(GrDirectContext * grContext,GrGpuResourceTag & tag)94 void MemoryManager::ReleaseAllGpuResource(GrDirectContext* grContext, GrGpuResourceTag& tag)
95 #else
96 void MemoryManager::ReleaseAllGpuResource(GrContext* grContext, GrGpuResourceTag& tag)
97 #endif
98 {
99 #ifdef RS_ENABLE_GL
100 if (!grContext) {
101 RS_LOGE("ReleaseGpuResByTag fail, grContext is nullptr");
102 }
103 RS_TRACE_NAME_FMT("ReleaseAllGpuResource [Pid:%d Tid:%d Nid:%d Funcid:%d]",
104 tag.fPid, tag.fTid, tag.fWid, tag.fFid);
105 grContext->releaseByTag(tag);
106 #endif
107 }
108 #else
109 #endif
110
111 #ifndef USE_ROSEN_DRAWING
112 #ifdef NEW_SKIA
ReleaseAllGpuResource(GrDirectContext * grContext,pid_t pid)113 void MemoryManager::ReleaseAllGpuResource(GrDirectContext* grContext, pid_t pid)
114 #else
115 void MemoryManager::ReleaseAllGpuResource(GrContext* grContext, pid_t pid)
116 #endif
117 {
118 #ifdef RS_ENABLE_GL
119 GrGpuResourceTag tag(pid, 0, 0, 0);
120 ReleaseAllGpuResource(grContext, tag);
121 #endif
122 }
123 #else
ReleaseAllGpuResource(Drawing::GPUContext * gpuContext,pid_t pid)124 void MemoryManager::ReleaseAllGpuResource(Drawing::GPUContext* gpuContext, pid_t pid)
125 {
126 }
127 #endif
128
129 #ifndef USE_ROSEN_DRAWING
130 #ifdef NEW_SKIA
ReleaseUnlockGpuResource(GrDirectContext * grContext,GrGpuResourceTag & tag)131 void MemoryManager::ReleaseUnlockGpuResource(GrDirectContext* grContext, GrGpuResourceTag& tag)
132 #else
133 void MemoryManager::ReleaseUnlockGpuResource(GrContext* grContext, GrGpuResourceTag& tag)
134 #endif
135 {
136 #ifdef RS_ENABLE_GL
137 if (!grContext) {
138 RS_LOGE("ReleaseGpuResByTag fail, grContext is nullptr");
139 }
140 RS_TRACE_NAME_FMT("ReleaseUnlockGpuResource [Pid:%d Tid:%d Nid:%d Funcid:%d]",
141 tag.fPid, tag.fTid, tag.fWid, tag.fFid);
142 grContext->purgeUnlockedResourcesByTag(false, tag);
143 #endif
144 }
145 #else
146 #endif
147
148 #ifndef USE_ROSEN_DRAWING
149 #ifdef NEW_SKIA
ReleaseUnlockGpuResource(GrDirectContext * grContext,NodeId surfaceNodeId)150 void MemoryManager::ReleaseUnlockGpuResource(GrDirectContext* grContext, NodeId surfaceNodeId)
151 #else
152 void MemoryManager::ReleaseUnlockGpuResource(GrContext* grContext, NodeId surfaceNodeId)
153 #endif
154 {
155 #ifdef RS_ENABLE_GL
156 GrGpuResourceTag tag(ExtractPid(surfaceNodeId), 0, 0, 0);
157 ReleaseUnlockGpuResource(grContext, tag); // clear gpu resource by pid
158 #endif
159 }
160 #else
ReleaseUnlockGpuResource(Drawing::GPUContext * grContext,NodeId surfaceNodeId)161 void MemoryManager::ReleaseUnlockGpuResource(Drawing::GPUContext* grContext, NodeId surfaceNodeId)
162 {
163 }
164 #endif
165
166 #ifndef USE_ROSEN_DRAWING
167 #ifdef NEW_SKIA
ReleaseUnlockGpuResource(GrDirectContext * grContext,pid_t pid)168 void MemoryManager::ReleaseUnlockGpuResource(GrDirectContext* grContext, pid_t pid)
169 #else
170 void MemoryManager::ReleaseUnlockGpuResource(GrContext* grContext, pid_t pid)
171 #endif
172 {
173 #ifdef RS_ENABLE_GL
174 GrGpuResourceTag tag(pid, 0, 0, 0);
175 ReleaseUnlockGpuResource(grContext, tag); // clear gpu resource by pid
176 #endif
177 }
178 #else
ReleaseUnlockGpuResource(Drawing::GPUContext * grContext,pid_t pid)179 void MemoryManager::ReleaseUnlockGpuResource(Drawing::GPUContext* grContext, pid_t pid)
180 {
181 }
182 #endif
183
184 #ifndef USE_ROSEN_DRAWING
185 #ifdef NEW_SKIA
ReleaseUnlockGpuResource(GrDirectContext * grContext,bool scratchResourcesOnly)186 void MemoryManager::ReleaseUnlockGpuResource(GrDirectContext* grContext, bool scratchResourcesOnly)
187 #else
188 void MemoryManager::ReleaseUnlockGpuResource(GrContext* grContext, bool scratchResourcesOnly)
189 #endif
190 {
191 #ifdef RS_ENABLE_GL
192 if (!grContext) {
193 RS_LOGE("ReleaseGpuResByTag fail, grContext is nullptr");
194 }
195 RS_TRACE_NAME_FMT("ReleaseUnlockGpuResource scratchResourcesOnly:%d", scratchResourcesOnly);
196 grContext->purgeUnlockedResources(scratchResourcesOnly);
197 #endif
198 }
199 #else
ReleaseUnlockGpuResource(Drawing::GPUContext * gpuContext,bool scratchResourcesOnly)200 void MemoryManager::ReleaseUnlockGpuResource(Drawing::GPUContext* gpuContext, bool scratchResourcesOnly)
201 {
202 #ifdef RS_ENABLE_GL
203 if (!gpuContext) {
204 RS_LOGE("ReleaseGpuResByTag fail, gpuContext is nullptr");
205 }
206 RS_TRACE_NAME_FMT("ReleaseUnlockGpuResource scratchResourcesOnly:%d", scratchResourcesOnly);
207 #endif
208 }
209 #endif
210
211 #ifndef USE_ROSEN_DRAWING
212 #ifdef NEW_SKIA
ReleaseUnlockAndSafeCacheGpuResource(GrDirectContext * grContext)213 void MemoryManager::ReleaseUnlockAndSafeCacheGpuResource(GrDirectContext* grContext)
214 #else
215 void MemoryManager::ReleaseUnlockAndSafeCacheGpuResource(GrContext* grContext)
216 #endif
217 {
218 #ifdef RS_ENABLE_GL
219 if (!grContext) {
220 RS_LOGE("ReleaseUnlockAndSafeCacheGpuResource fail, grContext is nullptr");
221 }
222 RS_TRACE_NAME_FMT("ReleaseUnlockAndSafeCacheGpuResource");
223 grContext->purgeUnlockAndSafeCacheGpuResources();
224 #endif
225 }
226 #else
ReleaseUnlockAndSafeCacheGpuResource(Drawing::GPUContext * gpuContext)227 void MemoryManager::ReleaseUnlockAndSafeCacheGpuResource(Drawing::GPUContext* gpuContext)
228 {
229 #ifdef RS_ENABLE_GL
230 if (!gpuContext) {
231 RS_LOGE("ReleaseUnlockAndSafeCacheGpuResource fail, gpuContext is nullptr");
232 }
233 RS_TRACE_NAME_FMT("ReleaseUnlockAndSafeCacheGpuResource");
234 #endif
235 }
236 #endif
237
238 #ifndef USE_ROSEN_DRAWING
239 #ifdef NEW_SKIA
DumpPidMemory(DfxString & log,int pid,const GrDirectContext * grContext)240 void MemoryManager::DumpPidMemory(DfxString& log, int pid, const GrDirectContext* grContext)
241 #else
242 void MemoryManager::DumpPidMemory(DfxString& log, int pid, const GrContext* grContext)
243 #endif
244 {
245 //MemoryTrack::Instance().DumpMemoryStatistics(log, pid);
246 MemoryGraphic mem = CountPidMemory(pid, grContext);
247 log.AppendFormat("GPU Mem(MB):%f\n", mem.GetGpuMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
248 log.AppendFormat("CPU Mem(MB):%f\n", mem.GetCpuMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
249 log.AppendFormat("Total Mem(MB):%f\n", mem.GetTotalMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
250 }
251 #else
DumpPidMemory(DfxString & log,int pid,const Drawing::GPUContext * gpuContext)252 void MemoryManager::DumpPidMemory(DfxString& log, int pid, const Drawing::GPUContext* gpuContext)
253 {
254 MemoryGraphic mem = CountPidMemory(pid, gpuContext);
255 log.AppendFormat("GPU Mem(MB):%f\n", mem.GetGpuMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
256 log.AppendFormat("CPU Mem(KB):%f\n", mem.GetCpuMemorySize() / MEMUNIT_RATE);
257 log.AppendFormat("Total Mem(MB):%f\n", mem.GetTotalMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
258 }
259 #endif
260
261 #ifndef USE_ROSEN_DRAWING
262 #ifdef NEW_SKIA
CountPidMemory(int pid,const GrDirectContext * grContext)263 MemoryGraphic MemoryManager::CountPidMemory(int pid, const GrDirectContext* grContext)
264 #else
265 MemoryGraphic MemoryManager::CountPidMemory(int pid, const GrContext* grContext)
266 #endif
267 {
268 MemoryGraphic totalMemGraphic;
269
270 // Count mem of RS
271 totalMemGraphic.SetPid(pid);
272 MemoryGraphic rsMemGraphic = MemoryTrack::Instance().CountRSMemory(pid);
273 totalMemGraphic += rsMemGraphic;
274
275 #ifdef RS_ENABLE_GL
276 // Count mem of Skia GPU
277 if (grContext) {
278 SkiaMemoryTracer gpuTracer("category", true);
279 GrGpuResourceTag tag(pid, 0, 0, 0);
280 grContext->dumpMemoryStatisticsByTag(&gpuTracer, tag);
281 float gpuMem = gpuTracer.GetGLMemorySize();
282 totalMemGraphic.IncreaseGpuMemory(gpuMem);
283 }
284 #endif
285
286 return totalMemGraphic;
287 }
288 #else
CountPidMemory(int pid,const Drawing::GPUContext * gpuContext)289 MemoryGraphic MemoryManager::CountPidMemory(int pid, const Drawing::GPUContext* gpuContext)
290 {
291 MemoryGraphic totalMemGraphic;
292
293 // Count mem of RS
294 totalMemGraphic.SetPid(pid);
295 MemoryGraphic rsMemGraphic = MemoryTrack::Instance().CountRSMemory(pid);
296 totalMemGraphic += rsMemGraphic;
297
298 #ifdef RS_ENABLE_GL
299 // Count mem of Skia GPU
300 #endif
301
302 return totalMemGraphic;
303 }
304 #endif
305
306 #ifndef USE_ROSEN_DRAWING
307 #ifdef NEW_SKIA
CountMemory(std::vector<pid_t> pids,const GrDirectContext * grContext,std::vector<MemoryGraphic> & mems)308 void MemoryManager::CountMemory(std::vector<pid_t> pids, const GrDirectContext* grContext,
309 std::vector<MemoryGraphic>& mems)
310 #else
311 void MemoryManager::CountMemory(std::vector<pid_t> pids, const GrContext* grContext, std::vector<MemoryGraphic>& mems)
312 #endif
313 {
314 auto countMem = [&grContext, &mems] (pid_t pid) {
315 mems.emplace_back(CountPidMemory(pid, grContext));
316 };
317 // Count mem of Skia GPU
318 std::for_each(pids.begin(), pids.end(), countMem);
319 }
320 #else
CountMemory(std::vector<pid_t> pids,const Drawing::GPUContext * gpuContext,std::vector<MemoryGraphic> & mems)321 void MemoryManager::CountMemory(
322 std::vector<pid_t> pids, const Drawing::GPUContext* gpuContext, std::vector<MemoryGraphic>& mems)
323 {
324 auto countMem = [&gpuContext, &mems] (pid_t pid) {
325 mems.emplace_back(CountPidMemory(pid, gpuContext));
326 };
327 // Count mem of Skia GPU
328 std::for_each(pids.begin(), pids.end(), countMem);
329 }
330 #endif
331
FindGeoById(uint64_t nodeId)332 static std::tuple<uint64_t, std::string, RectI> FindGeoById(uint64_t nodeId)
333 {
334 const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
335 auto node = nodeMap.GetRenderNode<RSRenderNode>(nodeId);
336 uint64_t windowId = nodeId;
337 std::string windowName = "NONE";
338 RectI nodeFrameRect;
339 if (!node) {
340 return { windowId, windowName, nodeFrameRect };
341 }
342 nodeFrameRect =
343 (node->GetRenderProperties().GetBoundsGeometry())->GetAbsRect();
344 // Obtain the window according to childId
345 auto parent = node->GetParent().lock();
346 while (parent) {
347 if (parent->IsInstanceOf<RSSurfaceRenderNode>()) {
348 const auto& surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(parent);
349 windowName = surfaceNode->GetName();
350 windowId = surfaceNode->GetId();
351 break;
352 }
353 parent = parent->GetParent().lock();
354 }
355 return { windowId, windowName, nodeFrameRect };
356 }
357
DumpRenderServiceMemory(DfxString & log)358 void MemoryManager::DumpRenderServiceMemory(DfxString& log)
359 {
360 log.AppendFormat("\n----------\nRenderService caches:\n");
361 MemoryTrack::Instance().DumpMemoryStatistics(log, FindGeoById);
362 }
363
DumpDrawingCpuMemory(DfxString & log)364 void MemoryManager::DumpDrawingCpuMemory(DfxString& log)
365 {
366 // CPU
367 log.AppendFormat("\n----------\nSkia CPU caches:\n");
368 log.AppendFormat("Font Cache (CPU):\n");
369 log.AppendFormat(" Size: %.2f kB \n", SkGraphics::GetFontCacheUsed() / MEMUNIT_RATE);
370 log.AppendFormat(" Glyph Count: %d \n", SkGraphics::GetFontCacheCountUsed());
371
372 std::vector<ResourcePair> cpuResourceMap = {
373 { "skia/sk_resource_cache/bitmap_", "Bitmaps" },
374 { "skia/sk_resource_cache/rrect-blur_", "Masks" },
375 { "skia/sk_resource_cache/rects-blur_", "Masks" },
376 { "skia/sk_resource_cache/tessellated", "Shadows" },
377 { "skia/sk_resource_cache/yuv-planes_", "YUVPlanes" },
378 { "skia/sk_resource_cache/budget_glyph_count", "Bitmaps" },
379 };
380 SkiaMemoryTracer cpuTracer(cpuResourceMap, true);
381 SkGraphics::DumpMemoryStatistics(&cpuTracer);
382 log.AppendFormat("CPU Cachesxx:\n");
383 cpuTracer.LogOutput(log);
384 log.AppendFormat("Total CPU memory usage:\n");
385 cpuTracer.LogTotals(log);
386
387 // cache limit
388 size_t cacheLimit = SkGraphics::GetResourceCacheTotalByteLimit();
389 size_t fontCacheLimit = SkGraphics::GetFontCacheLimit();
390 log.AppendFormat("\ncpu cache limit = %zu ( fontcache = %zu ):\n", cacheLimit, fontCacheLimit);
391 }
392
393 #ifndef USE_ROSEN_DRAWING
394 #ifdef NEW_SKIA
DumpGpuCache(DfxString & log,const GrDirectContext * grContext,GrGpuResourceTag * tag,std::string & name)395 void MemoryManager::DumpGpuCache(
396 DfxString& log, const GrDirectContext* grContext, GrGpuResourceTag* tag, std::string& name)
397 #else
398 void MemoryManager::DumpGpuCache(DfxString& log, const GrContext* grContext, GrGpuResourceTag* tag, std::string& name)
399 #endif
400 {
401 if (!grContext) {
402 log.AppendFormat("grContext is nullptr.\n");
403 return;
404 }
405 /////////////////////////////GPU/////////////////////////
406 #ifdef RS_ENABLE_GL
407 log.AppendFormat("\n---------------\nSkia GPU Caches:%s\n", name.c_str());
408 SkiaMemoryTracer gpuTracer("category", true);
409 if (tag) {
410 grContext->dumpMemoryStatisticsByTag(&gpuTracer, *tag);
411 } else {
412 grContext->dumpMemoryStatistics(&gpuTracer);
413 }
414 gpuTracer.LogOutput(log);
415 log.AppendFormat("Total GPU memory usage:\n");
416 gpuTracer.LogTotals(log);
417 #endif
418 }
419 #else
420 #endif
421
422 #ifndef USE_ROSEN_DRAWING
423 #ifdef NEW_SKIA
DumpAllGpuInfo(DfxString & log,const GrDirectContext * grContext)424 void MemoryManager::DumpAllGpuInfo(DfxString& log, const GrDirectContext* grContext)
425 #else
426 void MemoryManager::DumpAllGpuInfo(DfxString& log, const GrContext* grContext)
427 #endif
428 {
429 if (!grContext) {
430 log.AppendFormat("No valid gpu cache instance.\n");
431 return;
432 }
433 #ifdef RS_ENABLE_GL
434 const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
435 nodeMap.TraverseSurfaceNodes([&log, &grContext](const std::shared_ptr<RSSurfaceRenderNode> node) {
436 GrGpuResourceTag tag(ExtractPid(node->GetId()), 0, node->GetId(), 0);
437 std::string name = node->GetName() + " " + std::to_string(node->GetId());
438 DumpGpuCache(log, grContext, &tag, name);
439 });
440 #endif
441 }
442 #else
DumpAllGpuInfo(DfxString & log,const Drawing::GPUContext * gpuContext)443 void MemoryManager::DumpAllGpuInfo(DfxString& log, const Drawing::GPUContext* gpuContext)
444 {
445 if (!gpuContext) {
446 log.AppendFormat("No valid gpu cache instance.\n");
447 return;
448 }
449 #ifdef RS_ENABLE_GL
450 const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
451 nodeMap.TraverseSurfaceNodes([&log, &gpuContext](const std::shared_ptr<RSSurfaceRenderNode> node) {
452 });
453 #endif
454 }
455 #endif
456
457 #ifndef USE_ROSEN_DRAWING
458 #ifdef NEW_SKIA
DumpDrawingGpuMemory(DfxString & log,const GrDirectContext * grContext)459 void MemoryManager::DumpDrawingGpuMemory(DfxString& log, const GrDirectContext* grContext)
460 #else
461 void MemoryManager::DumpDrawingGpuMemory(DfxString& log, const GrContext* grContext)
462 #endif
463 {
464 if (!grContext) {
465 log.AppendFormat("No valid gpu cache instance.\n");
466 return;
467 }
468 /////////////////////////////GPU/////////////////////////
469 #ifdef RS_ENABLE_GL
470 std::string gpuInfo;
471 // total
472 DumpGpuCache(log, grContext, nullptr, gpuInfo);
473 // Get memory of window by tag
474 DumpAllGpuInfo(log, grContext);
475 for (uint32_t tagtype = RSTagTracker::TAG_SAVELAYER_DRAW_NODE; tagtype <= RSTagTracker::TAG_CAPTURE; tagtype++) {
476 GrGpuResourceTag tag(0, 0, 0, tagtype);
477 std::string tagType = RSTagTracker::TagType2String(static_cast<RSTagTracker::TAGTYPE>(tagtype));
478 DumpGpuCache(log, grContext, &tag, tagType);
479 }
480 // cache limit
481 size_t cacheLimit = 0;
482 size_t cacheUsed = 0;
483 grContext->getResourceCacheLimits(nullptr, &cacheLimit);
484 grContext->getResourceCacheUsage(nullptr, &cacheUsed);
485 log.AppendFormat("\ngpu limit = %zu ( used = %zu ):\n", cacheLimit, cacheUsed);
486
487 //////////////////////////ShaderCache///////////////////
488 log.AppendFormat("\n---------------\nShader Caches:\n");
489 #ifdef NEW_RENDER_CONTEXT
490 log.AppendFormat(MemoryHandler::QuerryShader().c_str());
491 #else
492 std::shared_ptr<RenderContext> rendercontext = std::make_shared<RenderContext>();
493 log.AppendFormat(rendercontext->GetShaderCacheSize().c_str());
494 #endif
495 // gpu stat
496 log.AppendFormat("\n---------------\ndumpGpuStats:\n");
497 SkString stat;
498 grContext->priv().dumpGpuStats(&stat);
499
500 log.AppendFormat("%s\n", stat.c_str());
501 #endif
502 }
503 #else
DumpDrawingGpuMemory(DfxString & log,const Drawing::GPUContext * gpuContext)504 void MemoryManager::DumpDrawingGpuMemory(DfxString& log, const Drawing::GPUContext* gpuContext)
505 {
506 }
507 #endif
508
DumpMallocStat(std::string & log)509 void MemoryManager::DumpMallocStat(std::string& log)
510 {
511 malloc_stats_print(
512 [](void* fp, const char* str) {
513 if (!fp) {
514 RS_LOGE("DumpMallocStat fp is nullptr");
515 return;
516 }
517 std::string* sp = static_cast<std::string*>(fp);
518 if (str) {
519 // cause log only support 2096 len. we need to only output critical log
520 // and only put total log in RSLOG
521 // get allocated string
522 if (strncmp(str, "Allocated", strlen("Allocated")) == 0) {
523 sp->append(str);
524 }
525 RS_LOGW("[mallocstat]:%s", str);
526 }
527 },
528 &log, nullptr);
529 }
530 } // namespace OHOS::Rosen