[dali_2.3.24] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / internal / system / common / object-profiler.cpp
1 /*
2  * Copyright (c) 20227 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/system/common/object-profiler.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/profiling.h>
24 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
25 #include <dali/public-api/images/pixel-data.h>
26 #include <dali/public-api/object/base-object.h>
27 #include <dali/public-api/object/ref-object.h>
28 #include <dali/public-api/object/type-registry.h>
29
30 #include <stdlib.h>
31
32 using std::string;
33 using namespace Dali::Integration::Profiling;
34
35 namespace Dali
36 {
37 namespace Internal
38 {
39 namespace Adaptor
40 {
41 ObjectProfiler::ObjectProfiler(Dali::ObjectRegistry objectRegistry, uint32_t timeInterval)
42 : mObjectRegistry(objectRegistry)
43 {
44   // This class must be created after the Stage; this means it doesn't count the initial objects
45   // that are created by the stage (base layer, default camera actor)
46
47   mTimer = Dali::Timer::New(timeInterval * 1000);
48   mTimer.TickSignal().Connect(this, &ObjectProfiler::OnTimeout);
49   mTimer.Start();
50
51   mObjectRegistry.ObjectCreatedSignal().Connect(this, &ObjectProfiler::OnObjectCreated);
52   mObjectRegistry.ObjectDestroyedSignal().Connect(this, &ObjectProfiler::OnObjectDestroyed);
53 }
54
55 ObjectProfiler::~ObjectProfiler()
56 {
57 }
58
59 void ObjectProfiler::DisplayInstanceCounts()
60 {
61   for(auto&& element : mInstanceCountContainer)
62   {
63     std::size_t memorySize = GetMemorySize(element.first, element.second);
64     if(memorySize > 0)
65     {
66       LogMessage(Debug::INFO, "%-30s: % 4d  Memory MemorySize: ~% 6.1f kB\n", element.first.c_str(), element.second, memorySize / 1024.0f);
67     }
68     else
69     {
70       LogMessage(Debug::INFO, "%-30s: % 4d\n", element.first.c_str(), element.second);
71     }
72   }
73   LogMessage(Debug::INFO, "\n");
74 }
75
76 bool ObjectProfiler::OnTimeout()
77 {
78   uint32_t pixelDataSize   = Dali::PixelData::GetTotalAllocatedSize();
79   uint32_t pixelBufferSize = Dali::Internal::Adaptor::PixelBuffer::GetTotalAllocatedSize();
80   LogMessage(Debug::INFO, "Total PixelData: %9.1fkb\n", ((float)pixelDataSize) / 1024.0f);
81   LogMessage(Debug::INFO, "Total PixelBuffer: %9.1fkb\n", ((float)pixelBufferSize) / 1024.0f);
82
83   DisplayInstanceCounts();
84   return true;
85 }
86
87 void ObjectProfiler::OnObjectCreated(BaseHandle handle)
88 {
89   string theType = handle.GetTypeName();
90   if(theType.empty())
91   {
92     DALI_LOG_ERROR("Object created from an unregistered type\n");
93     theType = "<Unregistered>";
94   }
95
96   mInstanceTypes.push_back(InstanceTypePair(&handle.GetBaseObject(), theType));
97
98   bool found = false;
99   for(auto&& element : mInstanceCountContainer)
100   {
101     if(element.first == theType)
102     {
103       element.second++;
104       found = true;
105     }
106   }
107   if(!found)
108   {
109     InstanceCountPair instanceCount(theType, 1);
110     mInstanceCountContainer.emplace_back(instanceCount);
111   }
112 }
113
114 void ObjectProfiler::OnObjectDestroyed(const Dali::RefObject* object)
115 {
116   const BaseObject* baseObject = static_cast<const BaseObject*>(object);
117
118   const auto end = mInstanceTypes.end();
119   for(auto iter = mInstanceTypes.begin(); iter != end; ++iter)
120   {
121     if(iter->first == baseObject)
122     {
123       const auto& theType = iter->second;
124       if(!theType.empty())
125       {
126         auto&& countIter = std::find_if(mInstanceCountContainer.begin(),
127                                         mInstanceCountContainer.end(),
128                                         [theType](const InstanceCountPair& instance) { return instance.first == theType; });
129         if(countIter != mInstanceCountContainer.end())
130         {
131           (*countIter).second--;
132         }
133       }
134       mInstanceTypes.erase(iter);
135       return;
136     }
137   }
138 }
139
140 std::size_t ObjectProfiler::GetMemorySize(const std::string& name, uint32_t count)
141 {
142   struct MemoryMemorySize
143   {
144     std::string name;
145     std::size_t memorySize;
146   };
147   MemoryMemorySize memoryMemorySizes[] =
148     {
149       {"Animation", ANIMATION_MEMORY_SIZE},
150       {"Constraint", CONSTRAINT_MEMORY_SIZE},
151       {"Actor", ACTOR_MEMORY_SIZE},
152       {"Layer", LAYER_MEMORY_SIZE},
153       {"CameraActor", CAMERA_ACTOR_MEMORY_SIZE},
154       {"Renderer", RENDERER_MEMORY_SIZE},
155       {"Geometry", GEOMETRY_MEMORY_SIZE},
156       {"PropertyBuffer", PROPERTY_BUFFER_MEMORY_SIZE},
157       {"TextureSet", TEXTURE_SET_MEMORY_SIZE},
158       {"Sampler", SAMPLER_MEMORY_SIZE},
159       {"Shader", SHADER_MEMORY_SIZE},
160     };
161
162   for(size_t i = 0; i < sizeof(memoryMemorySizes) / sizeof(MemoryMemorySize); i++)
163   {
164     if(memoryMemorySizes[i].name.compare(name) == 0)
165     {
166       return count * memoryMemorySizes[i].memorySize;
167     }
168   }
169   return 0;
170 }
171
172 } // namespace Adaptor
173 } // namespace Internal
174 } // namespace Dali