2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "performance-server.h"
22 #include <base/environment-options.h>
23 #include <dali/integration-api/platform-abstraction.h>
34 #define TIME_FMT "%0.2f ms" // 2 decimal places, e.g. 5.34 ms
35 #define TOTAL_TIME_FMT "%0.1f secs" // 1 decimal place, e.g. 4.5 seconds
41 const unsigned int DEFAULT_LOG_FREQUENCEY = 2; ///< default log frequency = 2
42 const unsigned int MILLISECONDS_PER_SECOND = 1000; ///< 1000 milliseconds per second
43 const unsigned int MICROSECONDS_PER_SECOND = 1000000; ///< 1000000 microseconds per second
45 const char* UPDATE_CONTEXT_NAME = "Update";
46 const char* RENDER_CONTEXT_NAME = "Render";
47 const char* EVENT_CONTEXT_NAME = "Event";
49 } // Anonymous namespace
52 PerformanceServer::PerformanceServer( AdaptorInternalServices& adaptorServices,
53 const EnvironmentOptions& environmentOptions)
54 :mPlatformAbstraction( adaptorServices.GetPlatformAbstractionInterface() ),
55 mEnvironmentOptions( environmentOptions ),
56 mKernelTrace( adaptorServices.GetKernelTraceInterface() ),
59 mLoggingEnabled( false ),
60 mLogFunctionInstalled( false )
63 mUpdateStats = AddContext( UPDATE_CONTEXT_NAME );
64 mRenderStats = AddContext( RENDER_CONTEXT_NAME );
65 mEventStats = AddContext( EVENT_CONTEXT_NAME );
67 SetLogging( mEnvironmentOptions.GetPerformanceLoggingLevel(), mEnvironmentOptions.GetFrameRateLoggingFrequency());
70 PerformanceServer::~PerformanceServer()
72 if( mLogFunctionInstalled )
74 mEnvironmentOptions.UnInstallLogFunction();
77 for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
79 StatContext* context = *it;
85 void PerformanceServer::SetLogging( unsigned int level, unsigned int logFrequency)
89 mLoggingEnabled = false;
94 EnableLogging( mLogLevel & LOG_UPDATE_RENDER, mUpdateStats );
95 EnableLogging( mLogLevel & LOG_UPDATE_RENDER, mRenderStats );
96 EnableLogging( mLogLevel & LOG_EVENT_PROCESS, mEventStats );
98 SetLoggingFrequency( logFrequency, mUpdateStats );
99 SetLoggingFrequency( logFrequency, mRenderStats );
100 SetLoggingFrequency( logFrequency, mEventStats );
102 mLoggingEnabled = true;
105 void PerformanceServer::SetLoggingFrequency( unsigned int logFrequency, ContextId contextId )
107 StatContext* context = GetContext( contextId );
110 unsigned int logFrequencyMicroseconds = logFrequency * MICROSECONDS_PER_SECOND;
112 if( logFrequencyMicroseconds == 0 )
114 logFrequencyMicroseconds = DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND;
117 context->SetLogFrequency( logFrequencyMicroseconds );
121 void PerformanceServer::EnableLogging( bool enable, ContextId contextId )
123 StatContext* context = GetContext( contextId );
126 context->EnableLogging( enable );
130 PerformanceServer::StatContext::StatContext()
133 mLogFrequencyMicroseconds( DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND ),
138 PerformanceServer::StatContext::StatContext( unsigned int id, const char* contextName )
139 : mName( contextName ),
141 mLogFrequencyMicroseconds( DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND ),
146 PerformanceInterface::ContextId PerformanceServer::AddContext( const char* name )
148 unsigned int contextId = mNextContextId++;
150 DALI_ASSERT_DEBUG( !GetContext( contextId ) );
152 mStatContexts.PushBack( new StatContext( contextId, name ) );
157 void PerformanceServer::RemoveContext( ContextId contextId )
159 for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
161 StatContext* context = *it;
163 if( context->GetId() == contextId )
167 mStatContexts.Erase( it );
173 PerformanceServer::StatContext* PerformanceServer::GetContext( ContextId contextId )
175 for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
177 StatContext* context = *it;
179 if( context->GetId() == contextId )
188 void PerformanceServer::AddMarker( MarkerType markerType )
194 for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
196 StatContext* context = *it;
198 AddMarker( VSYNC, context->GetId() );
204 AddMarker( START, mUpdateStats );
209 AddMarker( END, mUpdateStats );
214 AddMarker( START, mRenderStats );
219 AddMarker( END, mRenderStats );
222 case PROCESS_EVENTS_START:
224 AddMarker( START, mEventStats );
227 case PROCESS_EVENTS_END:
229 AddMarker( END, mEventStats );
239 void PerformanceServer::AddMarker( MarkerType markerType, ContextId contextId )
241 if( !mLoggingEnabled )
247 unsigned int seconds = 0;
248 unsigned int microseconds = 0;
249 mPlatformAbstraction.GetTimeMicroseconds( seconds, microseconds );
251 // Create a marker and add it to the log
252 PerformanceMarker marker( markerType, FrameTimeStamp( 0, seconds, microseconds ) );
253 AddMarkerToLog( marker, contextId );
256 void PerformanceServer::AddMarkerToLog( const PerformanceMarker& marker, ContextId contextId )
258 StatContext* context = GetContext( contextId );
261 if( mLogLevel & LOG_EVENTS_TO_KERNEL )
263 std::stringstream ss;
264 ss << GetMarkerName( marker.GetType() ) << ":" << ( ( context->GetName() ) ? context->GetName() : "" );
265 mKernelTrace.Trace( ss.str() );
268 // Only log on the v-sync thread, so we have less impact on update/render
269 if( marker.GetType() == VSYNC )
271 // make sure log function is installed, note this will be called only from v-sync thread
272 // if the v-sync thread has already installed one, it won't make any difference.
273 if( !mLogFunctionInstalled )
275 mEnvironmentOptions.InstallLogFunction();
276 mLogFunctionInstalled = true;
280 context->LogMarker( marker );
284 void PerformanceServer::StatContext::LogMarker()
286 float mean, standardDeviation;
287 mStats.CalculateMean( mean, standardDeviation );
289 // this will always log regardless of debug / release mode
290 Integration::Log::LogMessage( Dali::Integration::Log::DebugInfo,
291 "%s, min " TIME_FMT ", max " TIME_FMT ", total (" TOTAL_TIME_FMT "), avg " TIME_FMT ", std dev " TIME_FMT "\n",
292 ( mName ) ? mName : "",
293 mStats.GetMinTime() * MILLISECONDS_PER_SECOND,
294 mStats.GetMaxTime() * MILLISECONDS_PER_SECOND,
295 mStats.GetTotalTime(),
296 mean * MILLISECONDS_PER_SECOND,
297 standardDeviation * MILLISECONDS_PER_SECOND);
300 void PerformanceServer::StatContext::TimeMarkers()
302 // insert time stamps into a frame-time-stats object, based on type
303 for( MarkerVector::SizeType i = 0; i < mMarkers.Size(); ++i)
305 const PerformanceMarker& marker = mMarkers[i];
306 switch( marker.GetType() )
310 mStats.StartTime( marker.GetTimeStamp() );
315 mStats.EndTime( marker.GetTimeStamp() );
328 const char* PerformanceServer::GetMarkerName( MarkerType type ) const
349 DALI_ASSERT_DEBUG( !"Unsupported MarkerType" );
355 void PerformanceServer::StatContext::LogMarker( const PerformanceMarker& marker )
357 // Add Marker can be called from any thread
358 boost::mutex::scoped_lock sharedDatalock( mDataMutex );
360 mMarkers.PushBack( marker );
362 // Only log on the v-sync thread, so we have less impact on update/render
363 if( marker.GetType() == VSYNC )
365 // log out every mLogFrequency.
366 // check difference between first and last frame
367 unsigned int microseconds = PerformanceMarker::MicrosecondDiff( mMarkers[0], marker );
368 if( microseconds >= mLogFrequencyMicroseconds )
377 mStats.Reset(); // reset data for statistics
382 void PerformanceServer::StatContext::SetLogFrequency( unsigned int frequencyMicroseconds )
384 mLogFrequencyMicroseconds = frequencyMicroseconds;
387 void PerformanceServer::StatContext::EnableLogging( bool enableLogging )
389 mLog = enableLogging;
392 const char* PerformanceServer::StatContext::GetName() const
397 unsigned int PerformanceServer::StatContext::GetId() const
402 } // namespace Internal
404 } // namespace Adaptor