Merge branch 'devel/master' into tizen_4.0
[platform/core/uifw/dali-adaptor.git] / adaptors / common / object-profiler.cpp
1 /*
2  * Copyright (c) 2017 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 "object-profiler.h"
20
21 // EXTERNAL INCLUDES
22 #include <stdlib.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/integration-api/profiling.h>
25 #include <dali/public-api/common/stage.h>
26 #include <dali/public-api/object/ref-object.h>
27 #include <dali/public-api/object/base-object.h>
28 #include <dali/public-api/object/type-registry.h>
29
30 using std::string;
31 using namespace Dali::Integration::Profiling;
32
33 namespace Dali
34 {
35 namespace Internal
36 {
37 namespace Adaptor
38 {
39
40 ObjectProfiler::ObjectProfiler( unsigned int timeInterval )
41 {
42   // This class must be created after the Stage; this means it doesn't count the initial objects
43   // that are created by the stage (base layer, default camera actor)
44   mObjectRegistry = Dali::Stage::GetCurrent().GetObjectRegistry();
45
46   mTimer = Dali::Timer::New( timeInterval * 1000 );
47   mTimer.TickSignal().Connect( this, &ObjectProfiler::OnTimeout );
48   mTimer.Start();
49
50   mObjectRegistry.ObjectCreatedSignal().Connect( this, &ObjectProfiler::OnObjectCreated );
51   mObjectRegistry.ObjectDestroyedSignal().Connect( this, &ObjectProfiler::OnObjectDestroyed );
52 }
53
54 ObjectProfiler::~ObjectProfiler()
55 {
56 }
57
58 void ObjectProfiler::DisplayInstanceCounts()
59 {
60   for( auto&& element : mInstanceCountContainer )
61   {
62     int memorySize = GetMemorySize( element.first, element.second );
63     if( memorySize > 0 )
64     {
65       LogMessage( Debug::DebugInfo, "%-30s: % 4d  Memory MemorySize: ~% 6.1f kB\n",
66                   element.first.c_str(), element.second, memorySize / 1024.0f );
67     }
68     else
69     {
70       LogMessage( Debug::DebugInfo, "%-30s: % 4d\n",
71                   element.first.c_str(), element.second );
72     }
73   }
74   LogMessage(Debug::DebugInfo, "\n");
75 }
76
77 bool ObjectProfiler::OnTimeout()
78 {
79   DisplayInstanceCounts();
80   return true;
81 }
82
83 void ObjectProfiler::OnObjectCreated(BaseHandle handle)
84 {
85   string theType = handle.GetTypeName();
86   if( theType.empty() )
87   {
88     DALI_LOG_ERROR("Object created from an unregistered type\n");
89     theType = "<Unregistered>";
90   }
91
92   mInstanceTypes.push_back(InstanceTypePair(&handle.GetBaseObject(), theType));
93
94   bool found = false;
95   for( auto&& element : mInstanceCountContainer )
96   {
97     if( element.first == theType )
98     {
99       element.second++;
100       found = true;
101     }
102   }
103   if( !found )
104   {
105     InstanceCountPair instanceCount( theType, 1 );
106     mInstanceCountContainer.emplace_back( instanceCount );
107   }
108 }
109
110 void ObjectProfiler::OnObjectDestroyed(const Dali::RefObject* object)
111 {
112   const BaseObject* baseObject = static_cast<const BaseObject*>(object);
113
114   const auto end = mInstanceTypes.end();
115   for( auto iter = mInstanceTypes.begin(); iter != end; ++iter )
116   {
117     if( iter->first == baseObject )
118     {
119       const auto& theType = iter->second;
120       if( !theType.empty() )
121       {
122         auto&& countIter = std::find_if( mInstanceCountContainer.begin(),
123                                          mInstanceCountContainer.end(),
124                                          [theType] ( const InstanceCountPair& instance )
125                                                    { return instance.first == theType; } );
126         if( countIter != mInstanceCountContainer.end() )
127         {
128           (*countIter).second--;
129         }
130       }
131       mInstanceTypes.erase( iter );
132       return;
133     }
134   }
135 }
136
137 int ObjectProfiler::GetMemorySize(const std::string& name, int count)
138 {
139   struct MemoryMemorySize
140   {
141     std::string name;
142     int memorySize;
143   };
144   MemoryMemorySize memoryMemorySizes[] =
145     {
146       { "Animation", ANIMATION_MEMORY_SIZE },
147       { "Constraint", CONSTRAINT_MEMORY_SIZE },
148       { "Actor", ACTOR_MEMORY_SIZE },
149       { "Layer", LAYER_MEMORY_SIZE },
150       { "CameraActor", CAMERA_ACTOR_MEMORY_SIZE },
151       { "Image", IMAGE_MEMORY_SIZE },
152       { "Renderer", RENDERER_MEMORY_SIZE },
153       { "Geometry", GEOMETRY_MEMORY_SIZE },
154       { "PropertyBuffer", PROPERTY_BUFFER_MEMORY_SIZE },
155       { "TextureSet", TEXTURE_SET_MEMORY_SIZE },
156       { "Sampler", SAMPLER_MEMORY_SIZE },
157       { "Shader", SHADER_MEMORY_SIZE },
158     };
159
160   for( size_t i=0; i<sizeof(memoryMemorySizes)/sizeof(MemoryMemorySize); i++ )
161   {
162     if( memoryMemorySizes[i].name.compare(name) == 0 )
163     {
164       return count * memoryMemorySizes[i].memorySize;
165     }
166   }
167   return 0;
168 }
169
170 } // Adaptor
171 } // Internal
172 } // Dali