*
*/
-// INTERNAL INCLUDES
-#include <base/performance-logging/performance-marker.h>
-
-
namespace Dali
{
{
public:
+ typedef unsigned short ContextId; ///< Type to represent a context ID
+
/**
* bitmask of logging options
*/
enum LogLevel
{
DISABLED = 0,
- LOG_UPDATE_RENDER = 1 << 0, ///< Bit 0, log update and render times
- LOG_EVENT_PROCESS = 1 << 1, ///< Bit 1, log event process times
- LOG_EVENTS_TO_KERNEL = 1 << 2, ///< Bit 2, log all events to kernel trace
+ ENABLED = 1 << 0, ///< Bit 0, log all
+ LOG_UPDATE_RENDER = 1 << 1, ///< Bit 1, log update and render times
+ LOG_EVENT_PROCESS = 1 << 2, ///< Bit 2, log event process times
+ LOG_EVENTS_TO_KERNEL = 1 << 3 ///< Bit 3, log all events to kernel trace
+ };
+
+ /**
+ * enum for difference performance markers.
+ * Please modify the name lookup table in performance-interface.cpp
+ * file if adding new markers.
+ */
+ enum MarkerType
+ {
+ VSYNC = 0, ///< V-Sync
+ UPDATE_START , ///< Update start
+ UPDATE_END , ///< Update end
+ RENDER_START , ///< Render start
+ RENDER_END , ///< Render end
+ SWAP_START , ///< SwapBuffers Start
+ SWAP_END , ///< SwapBuffers End
+ PROCESS_EVENTS_START, ///< Process events start (e.g. touch event)
+ PROCESS_EVENTS_END, ///< Process events end
+ PAUSED , ///< Pause start
+ RESUME , ///< Resume start
+ START , ///< The start of custom tracking
+ END ///< The end of custom tracking
};
/**
virtual ~PerformanceInterface() {};
/**
+ * Add a new context with a given name
+ *
+ * @param[in] name The name of the context
+ * @return Return the unique id for this context
+ */
+ virtual ContextId AddContext( const char* name ) = 0;
+
+ /**
+ * Remove a context from use
+ *
+ * @param[in] contextId The ID of the context to remove
+ */
+ virtual void RemoveContext( ContextId contextId ) = 0;
+
+ /**
* Add a performance marker
* This function can be called from ANY THREAD.
+ * The default context 0 Event/Update/Render is assumed.
* @param markerType performance marker type
*/
- virtual void AddMarker( PerformanceMarker::MarkerType markerType) = 0;
+ virtual void AddMarker( MarkerType markerType ) = 0;
+
+ /**
+ * Add a performance marker
+ * This function can be called from ANY THREAD.
+ * @param markerType performance marker type
+ * @param contextId The context of the marker. This must be one generated by AddContext.
+ */
+ virtual void AddMarker( MarkerType markerType, ContextId contextId ) = 0;
/**
* Set the logging level and frequency
*/
virtual void SetLogging( unsigned int level, unsigned int logFrequency) = 0;
+ /**
+ * Set the logging frequency
+ *
+ * @param logFrequency how often to log out in seconds
+ */
+ virtual void SetLoggingFrequency( unsigned int logFrequency, ContextId contextId ) = 0;
+
+ /**
+ * Set logging on or off for a particular context
+ *
+ * @param[in] enable Enable logging or not
+ * @param[in] contextId The id of the context to log. This must be one generated by AddContext.
+ */
+ virtual void EnableLogging( bool enable, ContextId contextId ) = 0;
+
private:
// Undefined copy constructor.
// STRUCT HEADER
#include "frame-time-stats.h"
+#include <cmath>
+
namespace Dali
{
FrameTimeStats::FrameTimeStats()
: mTotal( 0.f)
{
+ mSamples.Reserve( 16 ); // Fill out a little to avoid early reallocations
+
Reset();
}
// frame time in seconds
unsigned int elapsedTime = FrameTimeStamp::MicrosecondDiff( mStart, timeStamp);
+ mSamples.PushBack( elapsedTime );
+
// if the min and max times haven't been set, do that now.
if( !mMinMaxTimeSet )
{
mMin = elapsedTime;
mMax = elapsedTime;
- mAvg = elapsedTime;
mMinMaxTimeSet = true;
}
else
}
mTotal += elapsedTime;
-
- // calculate a rolling average
- mAvg = (elapsedTime * (1.0f - EPSILON)) + (mAvg * EPSILON);
-
}
void FrameTimeStats::Reset()
mMinMaxTimeSet = false;
mMin = 0.f;
mMax = 0.f;
- mAvg = 0.f;
mRunCount = 0;
-}
-
-float FrameTimeStats::GetRollingAverageTime() const
-{
- return mAvg * ONE_OVER_MICROSECONDS_TO_SECONDS;
+ mSamples.Clear();
}
float FrameTimeStats::GetMaxTime() const
return mRunCount;
}
+void FrameTimeStats::CalculateMean( float& meanOut, float& standardDeviationOut ) const
+{
+ if( mSamples.Size() > 0 )
+ {
+ // Mean
+ unsigned int sum = 0;
+ for( Samples::ConstIterator it = mSamples.Begin(), itEnd = mSamples.End(); it != itEnd; ++it )
+ {
+ unsigned int value = *it;
+
+ sum += value;
+ }
+
+ meanOut = static_cast<float>(sum) / mSamples.Size();
+
+ // Variance
+ float variance = 0.0f;
+ for( Samples::ConstIterator it = mSamples.Begin(), itEnd = mSamples.End(); it != itEnd; ++it )
+ {
+ unsigned int value = *it;
+
+ float difference = static_cast<float>(value) - meanOut;
+
+ variance += difference * difference;
+ }
+
+ variance /= mSamples.Size();
+
+ // Standard deviation
+ standardDeviationOut = sqrtf( variance );
+
+ meanOut *= ONE_OVER_MICROSECONDS_TO_SECONDS;
+ standardDeviationOut *= ONE_OVER_MICROSECONDS_TO_SECONDS;
+ }
+ else
+ {
+ meanOut = 0.0f;
+ standardDeviationOut = 0.0f;
+ }
+}
+
} // namespace Adaptor
*/
// INTERNAL INCLUDES
+#include <base/performance-logging/frame-time-stamp.h>
+#include <dali/public-api/common/dali-vector.h>
-#include "frame-time-stamp.h"
namespace Dali
{
void Reset();
/**
- * @return rolling average time in seconds
- */
- float GetRollingAverageTime() const;
-
- /**
* @return maximum time in seconds
*/
float GetMaxTime() const;
*/
unsigned int GetRunCount() const;
+ /**
+ * Calculate the mean and standard deviation
+ *
+ * @param[out] mean The return mean value
+ * @param[out] standardDeviation The return standard deviation value
+ */
+ void CalculateMean( float& meanOut, float& standardDeviationOut ) const;
+
private:
/**
WAITING_FOR_END_TIME ///< waiting for end time marker
};
+ typedef Dali::Vector< unsigned int > Samples;
+ Samples mSamples;
+
unsigned int mMin; ///< current minimum value in microseconds
unsigned int mMax; ///< current maximum value in microseconds
- unsigned int mAvg; ///< current average in microseconds
unsigned int mTotal; ///< current total in in microseconds
unsigned int mRunCount; ///< how many times the timer has been start / stopped
FrameTimeStamp mStart; ///< start time stamp, to calculate the diff
namespace Adaptor
{
-namespace
-{
-
-struct NamePair
-{
- PerformanceMarker::MarkerType type;
- const char* name;
-};
-
-const NamePair MarkerLookup[] =
-{
- { PerformanceMarker::V_SYNC , "V_SYNC" },
- { PerformanceMarker::UPDATE_START , "UPDATE_START" },
- { PerformanceMarker::UPDATE_END , "UPDATE_END" },
- { PerformanceMarker::RENDER_START , "RENDER_START" },
- { PerformanceMarker::RENDER_END , "RENDER_END" },
- { PerformanceMarker::SWAP_START , "SWAP_START" },
- { PerformanceMarker::SWAP_END , "SWAP_END" },
- { PerformanceMarker::PROCESS_EVENTS_START, "PROCESS_EVENT_START" },
- { PerformanceMarker::PROCESS_EVENTS_END, "PROCESS_EVENT_END" },
- { PerformanceMarker::PAUSED , "PAUSED" },
- { PerformanceMarker::RESUME , "RESUMED" }
-};
-}
-PerformanceMarker::PerformanceMarker( MarkerType type )
+PerformanceMarker::PerformanceMarker( PerformanceInterface::MarkerType type )
:mType(type)
{
}
-PerformanceMarker::PerformanceMarker( MarkerType type, FrameTimeStamp frameInfo )
+PerformanceMarker::PerformanceMarker( PerformanceInterface::MarkerType type, FrameTimeStamp frameInfo )
:mType(type),
mTimeStamp(frameInfo)
{
}
-const char* PerformanceMarker::GetName( ) const
-{
- return MarkerLookup[ mType ].name;
-}
-
unsigned int PerformanceMarker::MicrosecondDiff( const PerformanceMarker& start,const PerformanceMarker& end )
{
return FrameTimeStamp::MicrosecondDiff( start.mTimeStamp, end.mTimeStamp );
*/
// INTERNAL INCLUDES
-#include "frame-time-stamp.h"
+#include <base/interfaces/performance-interface.h>
+#include <base/performance-logging/frame-time-stamp.h>
namespace Dali
{
public:
/**
- * enum for difference performance markers.
- * Please modify the name lookup table in performance-marker.cpp
- * file if adding new markers.
- */
- enum MarkerType
- {
- V_SYNC = 0, ///< V-Sync
- UPDATE_START , ///< Update start
- UPDATE_END , ///< Update end
- RENDER_START , ///< Render start
- RENDER_END , ///< Render end
- SWAP_START , ///< SwapBuffers Start
- SWAP_END , ///< SwapBuffers End
- PROCESS_EVENTS_START, ///< Process events start (e.g. touch event)
- PROCESS_EVENTS_END, ///< Process events end
- PAUSED , ///< Pause start
- RESUME ///< Resume start
- };
-
- /**
* Constructor
* @param type marker type
*/
- PerformanceMarker( MarkerType type);
+ PerformanceMarker( PerformanceInterface::MarkerType type );
/**
* Constructor
* @param type marker type
* @param time time stamp
*/
- PerformanceMarker(MarkerType type, FrameTimeStamp time);
+ PerformanceMarker( PerformanceInterface::MarkerType type, FrameTimeStamp time );
/**
* @return the time stamp
/**
* @return the type of marker
*/
- MarkerType GetType() const
+ PerformanceInterface::MarkerType GetType() const
{
return mType;
}
/**
- * @return the name of the marker
- */
- const char* GetName() const;
-
- /**
* @param start the start marker
* @param end the end marker
* @return difference in microseconds between two markers
private:
- MarkerType mType; ///< marker type
- FrameTimeStamp mTimeStamp; ///< frame time stamp
+ PerformanceInterface::MarkerType mType; ///< marker type
+ FrameTimeStamp mTimeStamp; ///< frame time stamp
};
namespace
{
+
const unsigned int DEFAULT_LOG_FREQUENCEY = 2; ///< default log frequency = 2
const unsigned int MILLISECONDS_PER_SECOND = 1000; ///< 1000 milliseconds per second
const unsigned int MICROSECONDS_PER_SECOND = 1000000; ///< 1000000 microseconds per second
-}
+
+const char* UPDATE_CONTEXT_NAME = "Update";
+const char* RENDER_CONTEXT_NAME = "Render";
+const char* EVENT_CONTEXT_NAME = "Event";
+
+} // Anonymous namespace
PerformanceServer::PerformanceServer( AdaptorInternalServices& adaptorServices,
const EnvironmentOptions& environmentOptions)
-:mLoggingEnabled( false),
- mLogFunctionInstalled( false ),
- mLogFrequencyMicroseconds( 0),
- mPlatformAbstraction( adaptorServices.GetPlatformAbstractionInterface() ),
- mEnvironmentOptions(environmentOptions),
- mKernelTrace( adaptorServices.GetKernelTraceInterface() )
+:mPlatformAbstraction( adaptorServices.GetPlatformAbstractionInterface() ),
+ mEnvironmentOptions( environmentOptions ),
+ mKernelTrace( adaptorServices.GetKernelTraceInterface() ),
+ mLogLevel( 0 ),
+ mNextContextId( 0 ),
+ mLoggingEnabled( false ),
+ mLogFunctionInstalled( false )
{
+ // Add defaults
+ mUpdateStats = AddContext( UPDATE_CONTEXT_NAME );
+ mRenderStats = AddContext( RENDER_CONTEXT_NAME );
+ mEventStats = AddContext( EVENT_CONTEXT_NAME );
+
SetLogging( mEnvironmentOptions.GetPerformanceLoggingLevel(), mEnvironmentOptions.GetFrameRateLoggingFrequency());
}
{
mEnvironmentOptions.UnInstallLogFunction();
}
+
+ for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
+ {
+ StatContext* context = *it;
+
+ delete context;
+ }
}
-void PerformanceServer::SetLogging( unsigned int level, unsigned int interval)
+
+void PerformanceServer::SetLogging( unsigned int level, unsigned int logFrequency)
{
- if( level == 0)
+ if( level == 0 )
{
mLoggingEnabled = false;
return;
}
mLogLevel = level;
- mLogFrequencyMicroseconds = interval * MICROSECONDS_PER_SECOND;
+ EnableLogging( mLogLevel & LOG_UPDATE_RENDER, mUpdateStats );
+ EnableLogging( mLogLevel & LOG_UPDATE_RENDER, mRenderStats );
+ EnableLogging( mLogLevel & LOG_EVENT_PROCESS, mEventStats );
+
+ SetLoggingFrequency( logFrequency, mUpdateStats );
+ SetLoggingFrequency( logFrequency, mRenderStats );
+ SetLoggingFrequency( logFrequency, mEventStats );
- if( mLogFrequencyMicroseconds == 0 )
- {
- mLogFrequencyMicroseconds = DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND;
- }
mLoggingEnabled = true;
+}
+void PerformanceServer::SetLoggingFrequency( unsigned int logFrequency, ContextId contextId )
+{
+ StatContext* context = GetContext( contextId );
+ if( context )
+ {
+ unsigned int logFrequencyMicroseconds = logFrequency * MICROSECONDS_PER_SECOND;
+
+ if( logFrequencyMicroseconds == 0 )
+ {
+ logFrequencyMicroseconds = DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND;
+ }
+
+ context->SetLogFrequency( logFrequencyMicroseconds );
+ }
}
-void PerformanceServer::AddMarker( PerformanceMarker::MarkerType markerType )
+void PerformanceServer::EnableLogging( bool enable, ContextId contextId )
{
- if( !mLoggingEnabled )
+ StatContext* context = GetContext( contextId );
+ if( context )
{
- return;
+ context->EnableLogging( enable );
}
+}
- unsigned int seconds(0);
- unsigned int microseconds(0);
+PerformanceServer::StatContext::StatContext()
+: mName( NULL ),
+ mId( 0 ),
+ mLogFrequencyMicroseconds( DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND ),
+ mLog( true )
+{
+}
- // get the time
- mPlatformAbstraction.GetTimeMicroseconds( seconds, microseconds );
+PerformanceServer::StatContext::StatContext( unsigned int id, const char* contextName )
+: mName( contextName ),
+ mId( id ),
+ mLogFrequencyMicroseconds( DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND ),
+ mLog( true )
+{
+}
+
+PerformanceInterface::ContextId PerformanceServer::AddContext( const char* name )
+{
+ unsigned int contextId = mNextContextId++;
- // create a marker
- PerformanceMarker marker( markerType, FrameTimeStamp( 0, seconds, microseconds ));
+ DALI_ASSERT_DEBUG( !GetContext( contextId ) );
- AddMarkerToLog( marker );
+ mStatContexts.PushBack( new StatContext( contextId, name ) );
+
+ return contextId;
}
-void PerformanceServer::AddMarkerToLog( PerformanceMarker marker )
+void PerformanceServer::RemoveContext( ContextId contextId )
{
- // Add Marker can be called from any thread
- boost::mutex::scoped_lock sharedDatalock( mDataMutex );
+ for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
+ {
+ StatContext* context = *it;
- // store the marker
- mMarkers.PushBack( marker );
+ if( context->GetId() == contextId )
+ {
+ delete context;
- if( mLogLevel & LOG_EVENTS_TO_KERNEL )
- {
- mKernelTrace.Trace(marker.GetName());
+ mStatContexts.Erase( it );
+ break;
+ }
}
+}
- // only log on the v-sync thread, so we have less impact on update/render
- if( marker.GetType() != PerformanceMarker::V_SYNC )
+PerformanceServer::StatContext* PerformanceServer::GetContext( ContextId contextId )
+{
+ for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
{
- return;
+ StatContext* context = *it;
+
+ if( context->GetId() == contextId )
+ {
+ return context;
+ }
}
- // log out every mLogFrequency.
- // check difference between first and last frame
- unsigned int microseconds = PerformanceMarker::MicrosecondDiff( mMarkers[0], marker );
+ return NULL;
+}
- if( microseconds >= mLogFrequencyMicroseconds )
+void PerformanceServer::AddMarker( MarkerType markerType )
+{
+ switch( markerType )
{
- LogMarkers( );
- mMarkers.Clear();
+ case VSYNC:
+ {
+ for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
+ {
+ StatContext* context = *it;
+
+ AddMarker( VSYNC, context->GetId() );
+ }
+ break;
+ }
+ case UPDATE_START:
+ {
+ AddMarker( START, mUpdateStats );
+ break;
+ }
+ case UPDATE_END:
+ {
+ AddMarker( END, mUpdateStats );
+ break;
+ }
+ case RENDER_START:
+ {
+ AddMarker( START, mRenderStats );
+ break;
+ }
+ case RENDER_END:
+ {
+ AddMarker( END, mRenderStats );
+ break;
+ }
+ case PROCESS_EVENTS_START:
+ {
+ AddMarker( START, mEventStats );
+ break;
+ }
+ case PROCESS_EVENTS_END:
+ {
+ AddMarker( END, mEventStats );
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
- // reset data for update / render statistics
- mUpdateStats.Reset();
- mRenderStats.Reset();
- mEventStats.Reset();
+void PerformanceServer::AddMarker( MarkerType markerType, ContextId contextId )
+{
+ if( !mLoggingEnabled )
+ {
+ return;
}
+
+ // Get the time
+ unsigned int seconds = 0;
+ unsigned int microseconds = 0;
+ mPlatformAbstraction.GetTimeMicroseconds( seconds, microseconds );
+
+ // Create a marker and add it to the log
+ PerformanceMarker marker( markerType, FrameTimeStamp( 0, seconds, microseconds ) );
+ AddMarkerToLog( marker, contextId );
}
-void PerformanceServer::LogMarker(const char* name, const FrameTimeStats& frameStats)
+void PerformanceServer::AddMarkerToLog( const PerformanceMarker& marker, ContextId contextId )
{
- // make sure log function is installed, note this will be called only from v-sync thread
- // if the v-sync thread has already installed one, it won't make any difference.
- if(! mLogFunctionInstalled )
+ StatContext* context = GetContext( contextId );
+ if( context )
{
- mEnvironmentOptions.InstallLogFunction();
- mLogFunctionInstalled = true;
+ if( mLogLevel & LOG_EVENTS_TO_KERNEL )
+ {
+ std::stringstream ss;
+ ss << GetMarkerName( marker.GetType() ) << ":" << ( ( context->GetName() ) ? context->GetName() : "" );
+ mKernelTrace.Trace( ss.str() );
+ }
+
+ // Only log on the v-sync thread, so we have less impact on update/render
+ if( marker.GetType() == VSYNC )
+ {
+ // make sure log function is installed, note this will be called only from v-sync thread
+ // if the v-sync thread has already installed one, it won't make any difference.
+ if( !mLogFunctionInstalled )
+ {
+ mEnvironmentOptions.InstallLogFunction();
+ mLogFunctionInstalled = true;
+ }
+ }
+
+ context->LogMarker( marker );
}
+}
+
+void PerformanceServer::StatContext::LogMarker()
+{
+ float mean, standardDeviation;
+ mStats.CalculateMean( mean, standardDeviation );
// this will always log regardless of debug / release mode
Integration::Log::LogMessage( Dali::Integration::Log::DebugInfo,
- "%s , min " TIME_FMT ", max " TIME_FMT ", total (" TOTAL_TIME_FMT "), avg " TIME_FMT "\n",
- name,
- frameStats.GetMinTime() * MILLISECONDS_PER_SECOND,
- frameStats.GetMaxTime() * MILLISECONDS_PER_SECOND,
- frameStats.GetTotalTime(),
- frameStats.GetRollingAverageTime() * MILLISECONDS_PER_SECOND);
+ "%s, min " TIME_FMT ", max " TIME_FMT ", total (" TOTAL_TIME_FMT "), avg " TIME_FMT ", std dev " TIME_FMT "\n",
+ ( mName ) ? mName : "",
+ mStats.GetMinTime() * MILLISECONDS_PER_SECOND,
+ mStats.GetMaxTime() * MILLISECONDS_PER_SECOND,
+ mStats.GetTotalTime(),
+ mean * MILLISECONDS_PER_SECOND,
+ standardDeviation * MILLISECONDS_PER_SECOND);
}
-void PerformanceServer::LogMarkers()
+void PerformanceServer::StatContext::TimeMarkers()
{
// insert time stamps into a frame-time-stats object, based on type
for( MarkerVector::SizeType i = 0; i < mMarkers.Size(); ++i)
const PerformanceMarker& marker = mMarkers[i];
switch( marker.GetType() )
{
- case PerformanceMarker::UPDATE_START:
+ case START:
{
- mUpdateStats.StartTime( marker.GetTimeStamp() );
+ mStats.StartTime( marker.GetTimeStamp() );
break;
}
- case PerformanceMarker::UPDATE_END:
+ case END:
{
- mUpdateStats.EndTime( marker.GetTimeStamp() );
- break;
- }
- case PerformanceMarker::RENDER_START:
- {
- mRenderStats.StartTime( marker.GetTimeStamp() );
- break;
- }
- case PerformanceMarker::RENDER_END:
- {
- mRenderStats.EndTime( marker.GetTimeStamp() );
- break;
- }
- case PerformanceMarker::PROCESS_EVENTS_START:
- {
- mEventStats.StartTime( marker.GetTimeStamp() );
- break;
- }
- case PerformanceMarker::PROCESS_EVENTS_END:
- {
- mEventStats.EndTime( marker.GetTimeStamp() );
+ mStats.EndTime( marker.GetTimeStamp() );
break;
}
default:
}
}
}
- if( mLogLevel & LOG_UPDATE_RENDER )
+
+ mMarkers.Clear();
+}
+
+const char* PerformanceServer::GetMarkerName( MarkerType type ) const
+{
+ switch( type )
{
- LogMarker("Update",mUpdateStats);
- LogMarker("Render",mRenderStats);
+ case VSYNC:
+ {
+ return "VSYNC";
+ }
+
+ case START:
+ {
+ return "START";
+ }
+
+ case END:
+ {
+ return "END";
+ }
+
+ default:
+ {
+ DALI_ASSERT_DEBUG( !"Unsupported MarkerType" );
+ return "";
+ }
}
- if( mLogLevel & LOG_EVENT_PROCESS )
+}
+
+void PerformanceServer::StatContext::LogMarker( const PerformanceMarker& marker )
+{
+ // Add Marker can be called from any thread
+ boost::mutex::scoped_lock sharedDatalock( mDataMutex );
+
+ mMarkers.PushBack( marker );
+
+ // Only log on the v-sync thread, so we have less impact on update/render
+ if( marker.GetType() == VSYNC )
{
- LogMarker("Event",mEventStats);
+ // log out every mLogFrequency.
+ // check difference between first and last frame
+ unsigned int microseconds = PerformanceMarker::MicrosecondDiff( mMarkers[0], marker );
+ if( microseconds >= mLogFrequencyMicroseconds )
+ {
+ TimeMarkers();
+
+ if( mLog )
+ {
+ LogMarker();
+ }
+
+ mStats.Reset(); // reset data for statistics
+ }
}
+}
+void PerformanceServer::StatContext::SetLogFrequency( unsigned int frequencyMicroseconds )
+{
+ mLogFrequencyMicroseconds = frequencyMicroseconds;
+}
+
+void PerformanceServer::StatContext::EnableLogging( bool enableLogging )
+{
+ mLog = enableLogging;
+}
+
+const char* PerformanceServer::StatContext::GetName() const
+{
+ return mName;
+}
+
+unsigned int PerformanceServer::StatContext::GetId() const
+{
+ return mId;
}
} // namespace Internal
#include <base/performance-logging/frame-time-stats.h>
#include <dali/public-api/common/dali-vector.h>
#include <base/interfaces/adaptor-internal-services.h>
+#include <base/performance-logging/performance-marker.h>
// EXTERNAL INCLUDES
#include <boost/thread/mutex.hpp>
{
class EnvironmentOptions;
+
/**
* Concrete implementation of performance interface.
* Adaptor classes should never include this file, they
*/
class PerformanceServer : public PerformanceInterface
{
-
public:
/**
virtual ~PerformanceServer();
/**
+ * @copydoc PerformanceLogger::AddContext()
+ */
+ virtual ContextId AddContext( const char* name );
+
+ /**
+ * @copydoc PerformanceLogger::RemoveContext()
+ */
+ virtual void RemoveContext( ContextId contextId );
+
+ /**
* @copydoc PerformanceInterface::AddMarker()
*/
- virtual void AddMarker( PerformanceMarker::MarkerType markerType);
+ virtual void AddMarker( MarkerType markerType );
+
+ /**
+ * @copydoc PerformanceLogger::AddMarker()
+ */
+ virtual void AddMarker( MarkerType markerType, ContextId contextId );
/**
* @copydoc PerformanceInterface::SetLogging()
*/
- virtual void SetLogging( unsigned int level, unsigned int interval);
+ virtual void SetLogging( unsigned int level, unsigned int logFrequency );
+
+ /**
+ * @copydoc PerformanceLogger::SetLoggingFrequency()
+ */
+ virtual void SetLoggingFrequency( unsigned int logFrequency, ContextId contextId );
+ /**
+ * @copydoc PerformanceLogger::EnableLogging()
+ */
+ virtual void EnableLogging( bool enable, ContextId contextId );
private:
/**
- * Helper
+ * Class to hold a stat context
*/
- void AddMarkerToLog( PerformanceMarker marker );
+ class StatContext
+ {
+ public:
+
+ /**
+ * Default constructor
+ */
+ StatContext();
+
+ /**
+ * Constructor
+ *
+ * @param[in] id The ID to give the context
+ * @param[in] contextName Name of the context to print in console
+ */
+ StatContext( unsigned int id, const char* contextName );
+
+ /**
+ * Return the ID
+ *
+ * @return Return the ID
+ */
+ unsigned int GetId() const;
+
+ /**
+ * Return the context name
+ *
+ * @return Return the context name
+ */
+ const char* GetName() const;
+
+ /**
+ * Log the given marker
+ *
+ * @param[in] marker The marker to log
+ */
+ void LogMarker( const PerformanceMarker& marker );
+
+ /**
+ * Set the frequency for logging
+ *
+ * @param[in] frequencyMicroseconds The frequency to set
+ */
+ void SetLogFrequency( unsigned int frequencyMicroseconds );
+
+ /**
+ * Enable/disable logging
+ *
+ * @param[in] enableLogging Flag to spePerformancecify enabling/disabling
+ */
+ void EnableLogging( bool enableLogging );
+
+ private:
+
+ /**
+ * Helper to print to console
+ */
+ void LogMarker();
+
+ /**
+ * Accumulate timer from markers
+ */
+ void TimeMarkers();
+
+ private:
+
+ typedef Dali::Vector< PerformanceMarker > MarkerVector;
+
+ FrameTimeStats mStats; ///< Frame time stats to accumulate
+ MarkerVector mMarkers; ///< vector of markers
+ boost::mutex mDataMutex; ///< mutex
+
+ const char* mName; ///< Name of the context
+
+ unsigned int mId; ///< The ID of the context
+
+ unsigned int mLogFrequencyMicroseconds; ///< if logging is enabled, what frequency to log out at in micro-seconds
+ bool mLog; ///< Whether to print the log for this context or not
+ };
/**
* Helper
*/
- void LogMarker(const char* name, const FrameTimeStats& frameStats);
+ void AddMarkerToLog( const PerformanceMarker& marker, ContextId contextId );
/**
- * log markers out
+ * Retrieve a stat context by ID
+ *
+ * @param[in] contextId The ID of the context to retrieve
+ * @return Return the stat context if it exists or null
*/
- void LogMarkers();
+ StatContext* GetContext( ContextId contextId );
-private:
+ /**
+ * Return a string representation of the marker type
+ *
+ * @param[in] type The marker type
+ * @return Return the name of the given marker
+ */
+ const char* GetMarkerName( MarkerType type ) const;
- bool mLoggingEnabled:1; ///< whether logging update / render to a log is enabled
- bool mLogFunctionInstalled:1; ///< whether the log function is installed
- unsigned int mLogLevel; ///< log level
+private:
- unsigned int mLogFrequencyMicroseconds; ///< if logging is enabled, what frequency to log out at in micro-seconds
+ typedef Dali::Vector< StatContext* > StatContexts;
- FrameTimeStats mUpdateStats; ///< update time statistics
- FrameTimeStats mRenderStats; ///< render time statistics
- FrameTimeStats mEventStats; ///< event time statistics
+ // The list of stat contexts
+ StatContexts mStatContexts;
Integration::PlatformAbstraction& mPlatformAbstraction; ///< platform abstraction
+ const EnvironmentOptions& mEnvironmentOptions; ///< environment options
+ KernelTraceInterface& mKernelTrace; ///< kernel trace interface
- typedef Dali::Vector<PerformanceMarker > MarkerVector;
- MarkerVector mMarkers; ///< vector of markers
- boost::mutex mDataMutex; ///< mutex
- const EnvironmentOptions& mEnvironmentOptions; ///< environment options
- KernelTraceInterface& mKernelTrace; ///< kernel trace interface
+ unsigned int mLogLevel; ///< log level
+ unsigned int mNextContextId; ///< The next valid context ID
+ // Some defaults
+ ContextId mUpdateStats; ///< update time statistics
+ ContextId mRenderStats; ///< render time statistics
+ ContextId mEventStats; ///< event time statistics
+
+ bool mLoggingEnabled:1; ///< whether logging update / render to a log is enabled
+ bool mLogFunctionInstalled:1; ///< whether the log function is installed
};
{
mPaused = true;
- AddPerformanceMarker( PerformanceMarker::PAUSED );
+ AddPerformanceMarker( PerformanceInterface::PAUSED );
mFrameTime.Suspend();
}
mPausedCondition.notify_one();
mVSyncSleepCondition.notify_one();
- AddPerformanceMarker( PerformanceMarker::RESUME);
+ AddPerformanceMarker( PerformanceInterface::RESUME);
}
void UpdateRenderSynchronization::UpdateRequested()
WaitSync();
}
- AddPerformanceMarker( PerformanceMarker::UPDATE_START );
+ AddPerformanceMarker( PerformanceInterface::UPDATE_START );
}
bool UpdateRenderSynchronization::UpdateSyncWithRender( bool& renderNeedsUpdate )
{
- AddPerformanceMarker( PerformanceMarker::UPDATE_END );
+ AddPerformanceMarker( PerformanceInterface::UPDATE_END );
boost::unique_lock< boost::mutex > lock( mMutex );
if( mRunning )
{
- AddPerformanceMarker( PerformanceMarker::RENDER_START );
+ AddPerformanceMarker( PerformanceInterface::RENDER_START );
}
// write any new requests
mRequestFinishedCondition.notify_one();
}
- AddPerformanceMarker( PerformanceMarker::RENDER_END );
+ AddPerformanceMarker( PerformanceInterface::RENDER_END );
}
void UpdateRenderSynchronization::WaitSync()
mVSyncReceivedCondition.notify_all();
- AddPerformanceMarker( PerformanceMarker::V_SYNC );
+ AddPerformanceMarker( PerformanceInterface::VSYNC );
while( mRunning && // sleep on condition variable WHILE still running
!mAllowUpdateWhilePaused && // AND NOT allowing updates while paused
mNumberOfVSyncsPerRender = numberOfVSyncsPerRender;
}
-inline void UpdateRenderSynchronization::AddPerformanceMarker( PerformanceMarker::MarkerType type )
+inline void UpdateRenderSynchronization::AddPerformanceMarker( PerformanceInterface::MarkerType type )
{
if( mPerformanceInterface )
{
* Helper to add a performance marker to the performance server (if its active)
* @param type performance marker type
*/
- void AddPerformanceMarker( PerformanceMarker::MarkerType type );
+ void AddPerformanceMarker( PerformanceInterface::MarkerType type );
private:
{
if( mPerformanceInterface )
{
- mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_START );
+ mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
}
mCore->ProcessEvents();
if( mPerformanceInterface )
{
- mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_END );
+ mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
}
}
}
$(adaptor_common_dir)/native-bitmap-buffer-impl.cpp \
$(adaptor_common_dir)/object-profiler.cpp \
$(adaptor_common_dir)/orientation-impl.cpp \
+ $(adaptor_common_dir)/performance-logger-impl.cpp \
$(adaptor_common_dir)/physical-keyboard-impl.cpp \
$(adaptor_common_dir)/render-surface-impl.cpp \
$(adaptor_common_dir)/server-connection.cpp \
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <performance-logger-impl.h>
+#include <adaptor-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+
+PerformanceInterface* GetPerformanceInterface()
+{
+ if( Adaptor::IsAvailable() )
+ {
+ return Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetPerformanceInterface();
+ }
+
+ return NULL;
+}
+
+} // Anonymous namespace
+
+PerformanceLoggerPtr PerformanceLogger::New( const char* name )
+{
+ PerformanceLoggerPtr logger = new PerformanceLogger( name );
+ return logger;
+}
+
+PerformanceLogger::PerformanceLogger( const char* name )
+: mContext( 0 )
+{
+ PerformanceInterface* performance = GetPerformanceInterface();
+ if( performance )
+ {
+ mContext = performance->AddContext( name );
+ }
+}
+
+PerformanceLogger::~PerformanceLogger()
+{
+ PerformanceInterface* performance = GetPerformanceInterface();
+ if( performance )
+ {
+ performance->RemoveContext( mContext );
+ }
+}
+
+void PerformanceLogger::AddMarker( Dali::PerformanceLogger::Marker markerType )
+{
+ PerformanceInterface* performance = GetPerformanceInterface();
+ if( performance )
+ {
+ PerformanceInterface::MarkerType newMarkerType = PerformanceInterface::START;
+ switch( markerType )
+ {
+ case Dali::PerformanceLogger::START_EVENT:
+ {
+ newMarkerType = PerformanceInterface::START;
+ break;
+ }
+ case Dali::PerformanceLogger::END_EVENT:
+ {
+ newMarkerType = PerformanceInterface::END;
+ break;
+ }
+ }
+
+ performance->AddMarker( newMarkerType, mContext );
+ }
+}
+
+void PerformanceLogger::SetLoggingFrequency( unsigned int logFrequency)
+{
+ PerformanceInterface* performance = GetPerformanceInterface();
+ if( performance )
+ {
+ performance->SetLoggingFrequency( logFrequency, mContext );
+ }
+}
+
+void PerformanceLogger::EnableLogging( bool enable )
+{
+ PerformanceInterface* performance = GetPerformanceInterface();
+ if( performance )
+ {
+ performance->EnableLogging( enable, mContext );
+ }
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_INTERNAL_PERFORMANCE_LOGGER_H__
+#define __DALI_INTERNAL_PERFORMANCE_LOGGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <base/interfaces/performance-interface.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/base-object.h>
+#include <performance-logger.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+class PerformanceLogger;
+
+typedef IntrusivePtr<PerformanceLogger> PerformanceLoggerPtr;
+
+/**
+ * @brief Interface for the performance logger
+ */
+class PerformanceLogger : public BaseObject
+{
+public:
+
+ /**
+ * @brief Create a new logger
+ *
+ * @param[in] name The name of the logger. This needs to be a compile-time literal and alive for the whole lifetime of the performance logger.
+ * @return a new logger
+ */
+ static PerformanceLoggerPtr New( const char* name );
+
+ /**
+ * Constructor
+ * @param[in] name The name to assing to the logger
+ */
+ PerformanceLogger( const char* name );
+
+ /**
+ * Destructor.
+ */
+ virtual ~PerformanceLogger();
+
+ /**
+ * Add a performance marker
+ *
+ * @param markerType Performance marker type
+ */
+ void AddMarker( Dali::PerformanceLogger::Marker markerType );
+
+ /**
+ * Set the logging frequency
+ *
+ * @param logFrequency how often to log out in seconds
+ */
+ void SetLoggingFrequency( unsigned int logFrequency);
+
+ /**
+ * Set logging on or off for this logger
+ *
+ * @param[in] enable Enable logging or not
+ */
+ void EnableLogging( bool enable );
+
+private: // Implementation
+
+ // not implemented
+ PerformanceLogger( const PerformanceLogger& );
+ PerformanceLogger& operator=( const PerformanceLogger& );
+
+private:
+
+ PerformanceInterface::ContextId mContext; ///< Context of this logger
+
+};
+
+// Helpers for public-api forwarding methods
+
+inline static Internal::Adaptor::PerformanceLogger& GetImplementation( Dali::PerformanceLogger& logger )
+{
+ DALI_ASSERT_ALWAYS( logger && "PerformanceLogger handle is empty" );
+
+ BaseObject& handle = logger.GetBaseObject();
+
+ return static_cast< Internal::Adaptor::PerformanceLogger& >( handle );
+}
+
+inline static const Internal::Adaptor::PerformanceLogger& GetImplementation( const Dali::PerformanceLogger& logger )
+{
+ DALI_ASSERT_ALWAYS( logger && "PerformanceLogger handle is empty" );
+
+ const BaseObject& handle = logger.GetBaseObject();
+
+ return static_cast< const Internal::Adaptor::PerformanceLogger& >( handle );
+}
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PERFORMANCE_LOGGER_H__
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <performance-logger.h>
+
+// INTERNAL INCLUDES
+#include <performance-logger-impl.h>
+
+namespace Dali
+{
+
+PerformanceLogger::PerformanceLogger()
+{
+}
+
+PerformanceLogger PerformanceLogger::New( const char* name )
+{
+ Internal::Adaptor::PerformanceLoggerPtr internal = Internal::Adaptor::PerformanceLogger::New( name );
+ return PerformanceLogger(internal.Get());
+}
+
+PerformanceLogger::PerformanceLogger( const PerformanceLogger& performanceLogger )
+: BaseHandle(performanceLogger)
+{
+}
+
+PerformanceLogger& PerformanceLogger::operator=( const PerformanceLogger& performanceLogger )
+{
+ // check self assignment
+ if( *this != performanceLogger )
+ {
+ BaseHandle::operator=(performanceLogger);
+ }
+ return *this;
+}
+
+PerformanceLogger::~PerformanceLogger()
+{
+}
+
+PerformanceLogger PerformanceLogger::DownCast( BaseHandle handle )
+{
+ return PerformanceLogger( dynamic_cast<Internal::Adaptor::PerformanceLogger*>( handle.GetObjectPtr() ) );
+}
+
+void PerformanceLogger::AddMarker( Marker markerType )
+{
+ Internal::Adaptor::GetImplementation(*this).AddMarker( markerType );
+}
+
+void PerformanceLogger::SetLoggingFrequency( unsigned int logFrequency)
+{
+ Internal::Adaptor::GetImplementation(*this).SetLoggingFrequency( logFrequency );
+}
+
+void PerformanceLogger::EnableLogging( bool enable )
+{
+ Internal::Adaptor::GetImplementation(*this).EnableLogging( enable );
+}
+
+PerformanceLogger::PerformanceLogger(Internal::Adaptor::PerformanceLogger* PerformanceLogger)
+: BaseHandle(PerformanceLogger)
+{
+}
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_PERFORMANCE_LOGGER_H__
+#define __DALI_PERFORMANCE_LOGGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+namespace Adaptor
+{
+class PerformanceLogger;
+}
+}
+
+/**
+ * @brief Performance logger class
+ */
+class DALI_IMPORT_API PerformanceLogger : public BaseHandle
+{
+public:
+
+ /**
+ * Enum for events that can be logged
+ */
+ enum Marker
+ {
+ START_EVENT, ///< The start of timing
+ END_EVENT ///< The end of timing
+ };
+
+ /**
+ * @brief Constructor, creates an uninitialized logger.
+ *
+ * Call New to fully construct a logger.
+ */
+ PerformanceLogger();
+
+ /**
+ * @brief Create a new logger
+ *
+ * @param[in] name The name of the logger. This needs to be a compile-time literal and alive for the whole lifetime of the performance logger.
+ * @return a new logger
+ */
+ static PerformanceLogger New( const char* name );
+
+ /**
+ * @brief Copy constructor.
+ *
+ * @param[in] logger The handle to copy. The copied handle will point at the same implementation
+ */
+ PerformanceLogger( const PerformanceLogger& logger );
+
+ /**
+ * @brief Assignment operator.
+ *
+ * @param[in] logger The handle to copy. This handle will point at the same implementation
+ * as the copied handle.
+ * @return Reference to this logger handle
+ */
+ PerformanceLogger& operator=( const PerformanceLogger& logger );
+
+ /**
+ * @brief Destructor
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ */
+ ~PerformanceLogger();
+
+ /**
+ * @brief Downcast an Object handle to PerformanceLogger handle.
+ *
+ * If handle points to a PerformanceLogger object the downcast produces a valid
+ * handle. If not the returned handle is left uninitialized.
+ *
+ * @param[in] handle to An object
+ * @return handle to a PerformanceLogger object or an uninitialized handle
+ */
+ static PerformanceLogger DownCast( BaseHandle handle );
+
+ /**
+ * Add a performance marker
+ *
+ * @param markerType Performance marker type
+ */
+ void AddMarker( Marker markerType );
+
+ /**
+ * Set the logging frequency
+ *
+ * @param logFrequency how often to log out in seconds
+ */
+ void SetLoggingFrequency( unsigned int logFrequency);
+
+ /**
+ * Set logging on or off for this logger
+ *
+ * @param[in] enable Enable logging or not
+ */
+ void EnableLogging( bool enable );
+
+ // Not intended for application developers
+
+ /**
+ * Creates a new handle from the implementation.
+ * @param[in] impl A pointer to the object.
+ */
+ explicit DALI_INTERNAL PerformanceLogger( Internal::Adaptor::PerformanceLogger* impl );
+
+};
+
+} // namespace Dali
+
+#endif // __DALI_PERFORMANCE_LOGGER_H__
#include <dali/public-api/adaptor-framework/lifecycle-controller.h>
#include <dali/public-api/adaptor-framework/orientation.h>
#include <dali/public-api/adaptor-framework/physical-keyboard.h>
+#include <dali/public-api/adaptor-framework/performance-logger.h>
#include <dali/public-api/adaptor-framework/pixmap-image.h>
#include <dali/public-api/adaptor-framework/render-surface.h>
#include <dali/public-api/adaptor-framework/singleton-service.h>
$(adaptor_public_api_dir)/adaptor-framework/lifecycle-controller.cpp \
$(adaptor_public_api_dir)/adaptor-framework/orientation.cpp \
$(adaptor_public_api_dir)/adaptor-framework/physical-keyboard.cpp \
+ $(adaptor_public_api_dir)/adaptor-framework/performance-logger.cpp \
$(adaptor_public_api_dir)/adaptor-framework/pixmap-image.cpp \
$(adaptor_public_api_dir)/adaptor-framework/render-surface.cpp \
$(adaptor_public_api_dir)/adaptor-framework/singleton-service.cpp \
$(adaptor_public_api_dir)/adaptor-framework/lifecycle-controller.h \
$(adaptor_public_api_dir)/adaptor-framework/orientation.h \
$(adaptor_public_api_dir)/adaptor-framework/physical-keyboard.h \
+ $(adaptor_public_api_dir)/adaptor-framework/performance-logger.h \
$(adaptor_public_api_dir)/adaptor-framework/pixmap-image.h \
$(adaptor_public_api_dir)/adaptor-framework/render-surface.h \
$(adaptor_public_api_dir)/adaptor-framework/singleton-service.h \