Seperated performance logging into 2 environment variables.
Plus added a new one for controlling the frequency of logging statistics
Before one environment variable would do multiple un-related things.
--DALI_LOG_PERFORMANCE_STATS--
A bitmask to control which DALi performance statstics are logged out.
The bitmask provided is
LOG_EVERYTHING ///< Bit 0 (1), log all statistics to the DALi log
LOG_UPDATE_RENDER ///< Bit 1 (2), log update and render statistics to the DALi log
LOG_EVENT_PROCESS ///< Bit 2 (4), log event task statistics to the DALi log
LOG_CUSTOM_MARKERS ///< Bit 3 (8), log custom marker statistics to the DALi log
Example output of running: DALI_LOG_PERFORMANCE_STATS=1 dali-demo
with a custom PerformanceLogger for dali-demo TableView Initialize()
INFO: DALI: Update, min 0.20 ms, max 2.47 ms, total (0.1 secs), avg 0.54 ms, std dev 0.25 ms
INFO: DALI: Render, min 0.06 ms, max 19.10 ms, total (0.1 secs), avg 0.94 ms, std dev 1.86 ms
INFO: DALI: Event, min 0.01 ms, max 9.38 ms, total (0.0 secs), avg 0.66 ms, std dev 2.02 ms
INFO: DALI: DaliTableView, min 81.11 ms, max 81.11 ms, total (0.1 secs), avg 81.11 ms, std dev 0.00 ms
--DALI_LOG_PERFORMANCE_STATS_FREQ--
Used to control the frequency of DALI_LOG_PERFORMANCE_STATS, e.g.
to log the statistics out every 5 seconds:
DALI_LOG_PERFORMANCE_STATS_FREQ=5 DALI_LOG_PERFORMANCE_STATS=1 dali-demo
--DALI_PERFORMANCE_TIMESTAMP_OUTPUT--
A bitmask to enable logging of time stamped events.
OUTPUT_DALI_LOG ///< Bit 1 (1), log markers to DALi log
OUTPUT_KERNEL_TRACE ///< Bit 2 (2), log makers to kernel trace
OUTPUT_SYSTEM_TRACE ///< Bit 3 (4), log markers to system trace ( currently not supported)
Example output of: DALI_PERFORMANCE_TIMESTAMP_OUTPUT=1 dali-demo
INFO: DALI: 966735.553251 (seconds), V_SYNC
INFO: DALI: 966735.553279 (seconds), UPDATE_START
INFO: DALI: 966735.553872 (seconds), UPDATE_END
INFO: DALI: 966735.553890 (seconds), RENDER_START
INFO: DALI: 966735.553933 (seconds), PROCESS_EVENT_START
INFO: DALI: 966735.554011 (seconds), PROCESS_EVENT_END
INFO: DALI: 966735.567137 (seconds), RENDER_END
INFO: DALI: 966735.570027 (seconds), V_SYNC
Change-Id: I392e9d3312111ce2d037e91b821996f43b4b842c
namespace Adaptor
{
+namespace
+{
+const unsigned int DEFAULT_STATISTICS_LOG_FREQUENCY = 2;
+}
EnvironmentOptions::EnvironmentOptions()
: mFpsFrequency(0),
mUpdateStatusFrequency(0),
- mPerformanceLoggingLevel(0),
+ mPerformanceStatsLevel(0),
+ mPerformanceStatsFrequency( DEFAULT_STATISTICS_LOG_FREQUENCY),
+ mPerformanceTimeStampOutput(0),
mPanGestureLoggingLevel(0),
mPanGesturePredictionMode(-1),
mPanGesturePredictionAmount(-1), ///< only sets value in pan gesture if greater than 0
void EnvironmentOptions::SetLogOptions( const Dali::Integration::Log::LogFunction& logFunction,
unsigned int logFrameRateFrequency,
unsigned int logupdateStatusFrequency,
- unsigned int logPerformanceLevel,
+ unsigned int logPerformanceStats,
+ unsigned int logPerformanceStatsFrequency,
+ unsigned int performanceTimeStampOutput,
unsigned int logPanGestureLevel )
{
mLogFunction = logFunction;
mFpsFrequency = logFrameRateFrequency;
mUpdateStatusFrequency = logupdateStatusFrequency;
- mPerformanceLoggingLevel = logPerformanceLevel;
+ mPerformanceStatsLevel = logPerformanceStats;
+ mPerformanceStatsFrequency = logPerformanceStatsFrequency;
+ mPerformanceTimeStampOutput= performanceTimeStampOutput;
mPanGestureLoggingLevel = logPanGestureLevel;
}
return mUpdateStatusFrequency;
}
-unsigned int EnvironmentOptions::GetPerformanceLoggingLevel() const
+unsigned int EnvironmentOptions::GetPerformanceStatsLoggingOptions() const
{
- return mPerformanceLoggingLevel;
+ return mPerformanceStatsLevel;
+}
+unsigned int EnvironmentOptions::GetPerformanceStatsLoggingFrequency() const
+{
+ return mPerformanceStatsFrequency;
+}
+unsigned int EnvironmentOptions::GetPerformanceTimeStampOutput() const
+{
+ return mPerformanceTimeStampOutput;
}
unsigned int EnvironmentOptions::GetPanGestureLoggingLevel() const
mGlesCallTime = time;
}
-int EnvironmentOptions::GetGlesCallTime()
+int EnvironmentOptions::GetGlesCallTime() const
{
return mGlesCallTime;
}
+bool EnvironmentOptions::PerformanceServerRequired() const
+{
+ return ( (GetPerformanceStatsLoggingOptions() > 0) ||
+ ( GetPerformanceTimeStampOutput() > 0 ) );
+}
+
} // Adaptor
} // Internal
* @param logFilterOptions bitmask of the logging options defined in intergration/debug.h (e.g.
* @param logFrameRateFrequency frequency of how often FPS is logged out (e.g. 0 = off, 2 = every 2 seconds).
* @param logupdateStatusFrequency frequency of how often the update status is logged in number of frames
- * @param logPerformanceLevel performance logging, 0 = disabled, 1+ = enabled
+ * @param logPerformanceStats performance statistics logging, 0 = disabled, 1+ = enabled
+ * @param logPerformanceStatsFrequency statistics logging frequency in seconds
+ * @param performanceTimeStampOutput where to output performance related time stamps to
* @param logPanGestureLevel pan-gesture logging, 0 = disabled, 1 = enabled
*/
void SetLogOptions( const Dali::Integration::Log::LogFunction& logFunction,
unsigned int logFrameRateFrequency,
unsigned int logupdateStatusFrequency,
- unsigned int logPerformanceLevel,
+ unsigned int logPerformanceStats,
+ unsigned int logPerformanceStatsFrequency,
+ unsigned int performanceTimeStampOutput,
unsigned int logPanGestureLevel );
/**
unsigned int GetUpdateStatusLoggingFrequency() const;
/**
- * @return logPerformanceLevel performance log level ( 0 = off )
+ * @return performance statistics log level ( 0 == off )
*/
- unsigned int GetPerformanceLoggingLevel() const;
+ unsigned int GetPerformanceStatsLoggingOptions() const;
+
+ /**
+ * @return performance statistics log frequency in seconds
+ */
+ unsigned int GetPerformanceStatsLoggingFrequency() const;
+
+ /**
+ * @return performance time stamp output ( 0 == off)
+ */
+ unsigned int GetPerformanceTimeStampOutput() const;
/**
* @return pan-gesture logging level ( 0 == off )
/**
* @brief Get the graphics status time
*/
- int GetGlesCallTime();
+ int GetGlesCallTime() const;
+ /**
+ * @return true if performance server is required
+ */
+ bool PerformanceServerRequired() const;
private:
unsigned int mFpsFrequency; ///< how often fps is logged out in seconds
unsigned int mUpdateStatusFrequency; ///< how often update status is logged out in frames
- unsigned int mPerformanceLoggingLevel; ///< performance log level
+ unsigned int mPerformanceStatsLevel; ///< performance statistics logging bitmask
+ unsigned int mPerformanceStatsFrequency; ///< performance statistics logging frequency (seconds)
+ unsigned int mPerformanceTimeStampOutput; ///< performance time stamp output ( bitmask)
unsigned int mPanGestureLoggingLevel; ///< pan-gesture log level
int mPanGesturePredictionMode; ///< prediction mode for pan gestures
int mPanGesturePredictionAmount; ///< prediction amount for pan gestures
namespace Adaptor
{
-#define DALI_ENV_LOG_PERFORMANCE "DALI_LOG_PERFORMANCE"
+/**
+ * What performance statistics are logged out to dlog
+ * see StatisticsLogOptions in performance-interface.h for values
+ */
+#define DALI_ENV_LOG_PERFORMANCE_STATS "DALI_LOG_PERFORMANCE_STATS"
+
+/**
+ * How frequent in seconds to log out performance statistics
+ */
+#define DALI_ENV_LOG_PERFORMANCE_STATS_FREQUENCY "DALI_LOG_PERFORMANCE_STATS_FREQ"
+
+/**
+ * Where timestamped events for update/render/event and custom events
+ * are output.
+ * see TimeStampOutput in performance-interface.h for values
+ */
+#define DALI_ENV_PERFORMANCE_TIMESTAMP_OUTPUT "DALI_PERFORMANCE_TIMESTAMP_OUTPUT"
// environment variable for enabling/disabling fps tracking
#define DALI_ENV_FPS_TRACKING "DALI_FPS_TRACKING"
$(base_adaptor_src_dir)/environment-options.cpp \
$(base_adaptor_src_dir)/performance-logging/frame-time-stats.cpp \
$(base_adaptor_src_dir)/performance-logging/performance-marker.cpp \
+ $(base_adaptor_src_dir)/performance-logging/statistics/stat-context.cpp \
+ $(base_adaptor_src_dir)/performance-logging/statistics/stat-context-manager.cpp \
$(base_adaptor_src_dir)/performance-logging/performance-server.cpp \
$(base_adaptor_src_dir)/performance-logging/performance-interface-factory.cpp
typedef unsigned short ContextId; ///< Type to represent a context ID
/**
- * bitmask of logging options
+ * bitmask of statistics logging options.
+ * Used for output data like min/max/average time spent in event, update,render and custom tasks.
+ * E.g.
+ * Event, min 0.04 ms, max 5.27 ms, total (0.1 secs), avg 0.28 ms, std dev 0.73 ms
+ * Update, min 0.29 ms, max 0.91 ms, total (0.5 secs), avg 0.68 ms, std dev 0.15 ms
+ * Render, min 0.33 ms, max 0.97 ms, total (0.6 secs), avg 0.73 ms, std dev 0.17 ms
+ * TableViewInit, min 76.55 ms, max 76.55 ms, total (0.1 secs), avg 76.55 ms, std dev 0.00 ms
*/
- enum LogLevel
+ enum StatisticsLogOptions
{
DISABLED = 0,
- 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
+ LOG_EVERYTHING = 1 << 0, ///< Bit 0 (1), log all statistics to the DALi log
+ LOG_UPDATE_RENDER = 1 << 1, ///< Bit 1 (2), log update and render statistics to the DALi log
+ LOG_EVENT_PROCESS = 1 << 2, ///< Bit 2 (4), log event task statistics to the DALi log
+ LOG_CUSTOM_MARKERS = 1 << 3, ///< Bit 3 (8), log custom marker statistics to the DALi log
+ };
+
+ /**
+ * bitmask of time stamp output options
+ * Used for logging out time stamped markers for detailed analysis (see MarkerType, for the markers logged)
+ * Typical output would look like:
+ * 379.059025 (seconds), V_SYNC
+ * 379.059066 (seconds), UPDATE_START
+ * 379.059747 (seconds), UPDATE_END
+ * 379.059820 (seconds), RENDER_START
+ * 379.060708 (seconds), RENDER_END
+ * 379.075795 (seconds), V_SYNC
+ * 379.076444 (seconds), MY_CUSTOM_MARKER_START ( customer marker using PerformanceLogger public API).
+ * 379.077353 (seconds), MY_CUSTOM_MARKER_END ( customer marker using PerformanceLogger public API).
+ */
+ enum TimeStampOutput
+ {
+ NO_TIME_STAMP_OUTPUT = 0,
+ OUTPUT_DALI_LOG = 1 << 0, ///< Bit 1 (1), log markers to DALi log
+ OUTPUT_KERNEL_TRACE = 1 << 1, ///< Bit 2 (2), log makers to kernel trace
+ OUTPUT_SYSTEM_TRACE = 1 << 2, ///< Bit 3 (4), log markers to system trace
+ OUTPUT_NETWORK = 1 << 3, ///< Bit 4 (8), log markers to network client
};
/**
* enum for difference performance markers.
* Please modify the name lookup table in performance-interface.cpp
- * file if adding new markers.
+ * file if adding new markers (the order must match one to one).
*/
enum MarkerType
{
virtual ~PerformanceInterface() {};
/**
- * Add a new context with a given name
+ * @brief 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
+ * @brief 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
+ * @brief 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
+ * @param[in] markerType performance marker type
*/
virtual void AddMarker( MarkerType markerType ) = 0;
/**
- * Add a performance marker
+ * @brief Add a performance marker for a used defined context
* 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.
+ * @param[in] markerType performance marker type
+ * @param[in] 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
- * @param level 0 = disabled, 1 = enabled
- * @param logFrequency how often to log out in seconds
+ * @brief Set the logging level and frequency
+ * @param[in] StatisticsLogOptions 0 = disabled, >0 bitmask of StatisticsLogOptions
+ * @param[in] timeStampOutput 0 = disabled, > 0 bitmask of TimeStampOutput options.
+ * @param[in] logFrequency how often to log out in seconds
*/
- virtual void SetLogging( unsigned int level, unsigned int logFrequency) = 0;
+ virtual void SetLogging( unsigned int statisticsLogOptions, unsigned int timeStampOutput, unsigned int logFrequency) = 0;
/**
- * Set the logging frequency
+ * @brief Set the logging frequency for an individual context
*
- * @param logFrequency how often to log out in seconds
+ * @param[in] 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
+ * @brief 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.
unsigned int FrameTimeStamp::MicrosecondDiff( const FrameTimeStamp& start,const FrameTimeStamp& end )
{
- unsigned int microDiff = end.microseconds - start.microseconds;
+ int microDiff = end.microseconds - start.microseconds;
unsigned int secDiff = ( end.seconds - start.seconds ) * MICROSECONDS_PER_SECOND;
return ( microDiff + secDiff);
}
// CLASS HEADER
#include "performance-marker.h"
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+
+
namespace Dali
{
namespace Adaptor
{
+namespace
+{
+
+struct NamePair
+{
+ PerformanceInterface::MarkerType type;
+ const char* const name;
+ PerformanceMarker::MarkerFilter group;
+ PerformanceMarker::MarkerEventType eventType;
+};
+
+const NamePair MARKER_LOOKUP[] =
+{
+ { PerformanceInterface::VSYNC , "V_SYNC" , PerformanceMarker::V_SYNC_EVENTS, PerformanceMarker::SINGLE_EVENT },
+ { PerformanceInterface::UPDATE_START , "UPDATE_START" , PerformanceMarker::UPDATE, PerformanceMarker::START_TIMED_EVENT },
+ { PerformanceInterface::UPDATE_END , "UPDATE_END" , PerformanceMarker::UPDATE, PerformanceMarker::END_TIMED_EVENT },
+ { PerformanceInterface::RENDER_START , "RENDER_START" , PerformanceMarker::RENDER, PerformanceMarker::START_TIMED_EVENT },
+ { PerformanceInterface::RENDER_END , "RENDER_END" , PerformanceMarker::RENDER, PerformanceMarker::END_TIMED_EVENT },
+ { PerformanceInterface::SWAP_START , "SWAP_START" , PerformanceMarker::SWAP_BUFFERS, PerformanceMarker::START_TIMED_EVENT },
+ { PerformanceInterface::SWAP_END , "SWAP_END" , PerformanceMarker::SWAP_BUFFERS, PerformanceMarker::END_TIMED_EVENT },
+ { PerformanceInterface::PROCESS_EVENTS_START, "PROCESS_EVENT_START" , PerformanceMarker::EVENT_PROCESS, PerformanceMarker::START_TIMED_EVENT },
+ { PerformanceInterface::PROCESS_EVENTS_END, "PROCESS_EVENT_END" , PerformanceMarker::EVENT_PROCESS, PerformanceMarker::END_TIMED_EVENT },
+ { PerformanceInterface::PAUSED , "PAUSED" , PerformanceMarker::LIFE_CYCLE_EVENTS, PerformanceMarker::SINGLE_EVENT },
+ { PerformanceInterface::RESUME , "RESUMED" , PerformanceMarker::LIFE_CYCLE_EVENTS, PerformanceMarker::SINGLE_EVENT },
+ { PerformanceInterface::START , "START" , PerformanceMarker::CUSTOM_EVENTS, PerformanceMarker::START_TIMED_EVENT },
+ { PerformanceInterface::END , "END" , PerformanceMarker::CUSTOM_EVENTS, PerformanceMarker::END_TIMED_EVENT }
+};
+} // un-named namespace
+
+
+
PerformanceMarker::PerformanceMarker( PerformanceInterface::MarkerType type )
:mType(type)
{
{
}
+const char* const PerformanceMarker::GetName( ) const
+{
+ return MARKER_LOOKUP[ mType ].name;
+}
+
+PerformanceMarker::MarkerEventType PerformanceMarker::GetEventType() const
+{
+ return MARKER_LOOKUP[ mType ].eventType;
+}
+
unsigned int PerformanceMarker::MicrosecondDiff( const PerformanceMarker& start,const PerformanceMarker& end )
{
return FrameTimeStamp::MicrosecondDiff( start.mTimeStamp, end.mTimeStamp );
}
+bool PerformanceMarker::IsFilterEnabled( MarkerFilter filter ) const
+{
+ return (filter & MARKER_LOOKUP[ mType ].group);
+}
+
+
} // namespace Adaptor
} // namespace Internal
{
public:
+
+ /**
+ * Bitmask used to filter different types of markers based
+ * on what group they belong to.
+ */
+ enum MarkerFilter
+ {
+ FILTERING_DISABLED = 0, ///< disabled
+ V_SYNC_EVENTS = 1 << 0, ///< v-sync
+ UPDATE = 1 << 1, ///< update start / end
+ RENDER = 1 << 2, ///< render start / end
+ EVENT_PROCESS = 1 << 3, ///< process events start / end
+ SWAP_BUFFERS = 1 << 4, ///< swap buffers start / end
+ LIFE_CYCLE_EVENTS = 1 << 5, ///< pause / resume
+ RESOURCE_EVENTS = 1 << 6, ///< resource events
+ CUSTOM_EVENTS = 1 << 7
+ };
+
/**
- * Constructor
- * @param type marker type
+ * Marker event type
+ */
+ enum MarkerEventType
+ {
+ SINGLE_EVENT, ///< event is something that has no duration associated with it
+ START_TIMED_EVENT, ///< start of a timed event
+ END_TIMED_EVENT ///< end of a timed event
+
+ };
+
+
+ /**
+ * @brief Constructor
+ * @param[in] type marker type
*/
PerformanceMarker( PerformanceInterface::MarkerType type );
/**
- * Constructor
- * @param type marker type
- * @param time time stamp
+ * @brief Constructor
+ * @param[in] type marker type
+ * @param[in] time time stamp
*/
PerformanceMarker( PerformanceInterface::MarkerType type, FrameTimeStamp time );
}
/**
+ * @return the event type of marker
+ */
+ MarkerEventType GetEventType() const;
+
+ /**
+ * @return marker name
+ */
+ const char* const GetName( ) const;
+
+ /**
* @param start the start marker
* @param end the end marker
* @return difference in microseconds between two markers
*/
static unsigned int MicrosecondDiff( const PerformanceMarker& start, const PerformanceMarker& end );
+ /**
+ * @return if a marker is enabled as part of a group
+ */
+ bool IsFilterEnabled( MarkerFilter filter ) const;
private:
PerformanceInterface::MarkerType mType; ///< marker type
namespace Adaptor
{
-#define TIME_FMT "%0.2f ms" // 2 decimal places, e.g. 5.34 ms
-#define TOTAL_TIME_FMT "%0.1f secs" // 1 decimal place, e.g. 4.5 seconds
-
-
-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)
:mPlatformAbstraction( adaptorServices.GetPlatformAbstractionInterface() ),
mEnvironmentOptions( environmentOptions ),
mKernelTrace( adaptorServices.GetKernelTraceInterface() ),
- mLogLevel( 0 ),
- mNextContextId( 0 ),
+ mStatContextManager( *this ),
+ mStatisticsLogBitmask( 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());
+ SetLogging( mEnvironmentOptions.GetPerformanceStatsLoggingOptions(),
+ mEnvironmentOptions.GetPerformanceTimeStampOutput(),
+ mEnvironmentOptions.GetPerformanceStatsLoggingFrequency());
}
PerformanceServer::~PerformanceServer()
{
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 logFrequency)
+void PerformanceServer::SetLogging( unsigned int statisticsLogOptions,
+ unsigned int timeStampOutput,
+ unsigned int logFrequency )
{
- if( level == 0 )
+ if( ( statisticsLogOptions == 0) && ( timeStampOutput == 0 ))
{
mLoggingEnabled = false;
return;
}
- mLogLevel = level;
- EnableLogging( mLogLevel & LOG_UPDATE_RENDER, mUpdateStats );
- EnableLogging( mLogLevel & LOG_UPDATE_RENDER, mRenderStats );
- EnableLogging( mLogLevel & LOG_EVENT_PROCESS, mEventStats );
+ mStatisticsLogBitmask = statisticsLogOptions;
+ mPerformanceOutputBitmask = timeStampOutput;
- SetLoggingFrequency( logFrequency, mUpdateStats );
- SetLoggingFrequency( logFrequency, mRenderStats );
- SetLoggingFrequency( logFrequency, mEventStats );
+ mStatContextManager.SetLoggingLevel( mStatisticsLogBitmask, logFrequency);
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 );
- }
+ mStatContextManager.SetLoggingFrequency( logFrequency, contextId );
}
void PerformanceServer::EnableLogging( bool enable, ContextId contextId )
{
- StatContext* context = GetContext( contextId );
- if( context )
- {
- context->EnableLogging( enable );
- }
-}
-
-PerformanceServer::StatContext::StatContext()
-: mName( NULL ),
- mId( 0 ),
- mLogFrequencyMicroseconds( DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND ),
- mLog( true )
-{
-}
-
-PerformanceServer::StatContext::StatContext( unsigned int id, const char* contextName )
-: mName( contextName ),
- mId( id ),
- mLogFrequencyMicroseconds( DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND ),
- mLog( true )
-{
+ mStatContextManager.EnableLogging( enable, contextId );
}
PerformanceInterface::ContextId PerformanceServer::AddContext( const char* name )
{
- unsigned int contextId = mNextContextId++;
-
- DALI_ASSERT_DEBUG( !GetContext( contextId ) );
-
- mStatContexts.PushBack( new StatContext( contextId, name ) );
-
- return contextId;
+ // for adding custom contexts
+ return mStatContextManager.AddContext( name, PerformanceMarker::CUSTOM_EVENTS );
}
void PerformanceServer::RemoveContext( ContextId contextId )
{
- for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
- {
- StatContext* context = *it;
-
- if( context->GetId() == contextId )
- {
- delete context;
-
- mStatContexts.Erase( it );
- break;
- }
- }
-}
-
-PerformanceServer::StatContext* PerformanceServer::GetContext( ContextId contextId )
-{
- for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
- {
- StatContext* context = *it;
-
- if( context->GetId() == contextId )
- {
- return context;
- }
- }
-
- return NULL;
-}
-
-void PerformanceServer::AddMarker( MarkerType markerType )
-{
- switch( markerType )
- {
- 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;
- }
- }
+ mStatContextManager.RemoveContext( contextId );
}
void PerformanceServer::AddMarker( MarkerType markerType, ContextId contextId )
{
+ // called only for custom markers
+
if( !mLoggingEnabled )
{
return;
}
- // Get the time
+ // This is only called from main event thread, but may overlap with internal AddMarker calls
+ // from other threads ( update, render etc).
+ boost::mutex::scoped_lock sharedDatalock( mDataMutex );
+
+ // Get the time stamp
unsigned int seconds = 0;
unsigned int microseconds = 0;
mPlatformAbstraction.GetTimeMicroseconds( seconds, microseconds );
- // Create a marker and add it to the log
+ // Create a marker
PerformanceMarker marker( markerType, FrameTimeStamp( 0, seconds, microseconds ) );
- AddMarkerToLog( marker, contextId );
-}
-void PerformanceServer::AddMarkerToLog( const PerformanceMarker& marker, ContextId contextId )
-{
- StatContext* context = GetContext( contextId );
- if( context )
- {
- if( mLogLevel & LOG_EVENTS_TO_KERNEL )
- {
- std::stringstream ss;
- ss << GetMarkerName( marker.GetType() ) << ":" << ( ( context->GetName() ) ? context->GetName() : "" );
- mKernelTrace.Trace( ss.str() );
- }
+ // get the marker description for this context, e.g SIZE_NEGOTIATION_START
+ const char* const description = mStatContextManager.GetMarkerDescription( markerType, contextId );
- // 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;
- }
- }
+ // log it
+ LogMarker( marker, description );
- context->LogMarker( marker );
- }
-}
+ // Add custom marker to statistics context manager
+ mStatContextManager.AddCustomMarker( marker, contextId );
-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 ", 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::StatContext::TimeMarkers()
+void PerformanceServer::AddMarker( MarkerType markerType )
{
- // insert time stamps into a frame-time-stats object, based on type
- for( MarkerVector::SizeType i = 0; i < mMarkers.Size(); ++i)
+ // called only for internal markers
+
+ if( !mLoggingEnabled )
{
- const PerformanceMarker& marker = mMarkers[i];
- switch( marker.GetType() )
- {
- case START:
- {
- mStats.StartTime( marker.GetTimeStamp() );
- break;
- }
- case END:
- {
- mStats.EndTime( marker.GetTimeStamp() );
- break;
- }
- default:
- {
- break;
- }
- }
+ return;
}
- mMarkers.Clear();
-}
+ // AddMarker can be called from multiple threads, to avoid problems
+ // with updating contexts and the kernel trace, lock here.
+ boost::mutex::scoped_lock sharedDatalock( mDataMutex );
-const char* PerformanceServer::GetMarkerName( MarkerType type ) const
-{
- switch( type )
+ if( markerType == VSYNC )
{
- case 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 )
{
- return "VSYNC";
- }
-
- case START:
- {
- return "START";
- }
-
- case END:
- {
- return "END";
- }
-
- default:
- {
- DALI_ASSERT_DEBUG( !"Unsupported MarkerType" );
- return "";
+ mEnvironmentOptions.InstallLogFunction();
+ mLogFunctionInstalled = true;
}
}
-}
-void PerformanceServer::StatContext::LogMarker( const PerformanceMarker& marker )
-{
- // Add Marker can be called from any thread
- boost::mutex::scoped_lock sharedDatalock( mDataMutex );
+ // Get the time
+ unsigned int seconds = 0;
+ unsigned int microseconds = 0;
+ mPlatformAbstraction.GetTimeMicroseconds( seconds, microseconds );
- mMarkers.PushBack( marker );
+ // Create a marker
+ PerformanceMarker marker( markerType, FrameTimeStamp( 0, seconds, microseconds ) );
- // Only log on the v-sync thread, so we have less impact on update/render
- if( marker.GetType() == VSYNC )
- {
- // log out every mLogFrequency.
- // check difference between first and last frame
- unsigned int microseconds = PerformanceMarker::MicrosecondDiff( mMarkers[0], marker );
- if( microseconds >= mLogFrequencyMicroseconds )
- {
- TimeMarkers();
+ // log it
+ LogMarker(marker, marker.GetName() );
- if( mLog )
- {
- LogMarker();
- }
+ // Add internal marker to statistics context manager
+ mStatContextManager.AddInternalMarker( marker );
- mStats.Reset(); // reset data for statistics
- }
- }
}
-void PerformanceServer::StatContext::SetLogFrequency( unsigned int frequencyMicroseconds )
+void PerformanceServer::LogContextStatistics( const char* const text )
{
- mLogFrequencyMicroseconds = frequencyMicroseconds;
+ Integration::Log::LogMessage( Dali::Integration::Log::DebugInfo, text );
}
-void PerformanceServer::StatContext::EnableLogging( bool enableLogging )
+void PerformanceServer::LogMarker( const PerformanceMarker& marker, const char* const description )
{
- mLog = enableLogging;
-}
-const char* PerformanceServer::StatContext::GetName() const
-{
- return mName;
-}
-unsigned int PerformanceServer::StatContext::GetId() const
-{
- return mId;
+
+ // log to kernel trace
+ if( mPerformanceOutputBitmask & OUTPUT_KERNEL_TRACE )
+ {
+ // name will be something like UPDATE_START or UPDATE_END
+ mKernelTrace.Trace( description );
+ }
+
+ // log to Dali log
+ if ( mPerformanceOutputBitmask & OUTPUT_DALI_LOG )
+ {
+ Integration::Log::LogMessage( Dali::Integration::Log::DebugInfo,
+ "%d.%06d (seconds), %s\n",
+ marker.GetTimeStamp().seconds,
+ marker.GetTimeStamp().microseconds,
+ description);
+ }
}
+
} // namespace Internal
} // namespace Adaptor
#include <dali/public-api/common/dali-vector.h>
#include <base/interfaces/adaptor-internal-services.h>
#include <base/performance-logging/performance-marker.h>
+#include <base/performance-logging/statistics/stat-context-manager.h>
// EXTERNAL INCLUDES
#include <boost/thread/mutex.hpp>
{
class EnvironmentOptions;
-
+class StatContext;
/**
* Concrete implementation of performance interface.
* Adaptor classes should never include this file, they
* just need to include the abstract class performance-interface.h
*/
-class PerformanceServer : public PerformanceInterface
+class PerformanceServer : public PerformanceInterface, public StatContextLogInterface
{
public:
/**
- * Constructor
- * @param adaptorServices adaptor internal services
- * @param environmentOptions environment options
+ * @brief Constructor
+ * @param[in] adaptorServices adaptor internal services
+ * @param[in] environmentOptions environment options
*/
PerformanceServer( AdaptorInternalServices& adaptorServices,
const EnvironmentOptions& environmentOptions );
virtual void RemoveContext( ContextId contextId );
/**
- * @copydoc PerformanceInterface::AddMarker()
+ * @copydoc PerformanceInterface::AddMarker( MarkerType markerType )
*/
virtual void AddMarker( MarkerType markerType );
/**
- * @copydoc PerformanceLogger::AddMarker()
+ * @copydoc PerformanceLogger::AddMarker( MarkerType markerType, ContextId contextId )
*/
virtual void AddMarker( MarkerType markerType, ContextId contextId );
/**
* @copydoc PerformanceInterface::SetLogging()
*/
- virtual void SetLogging( unsigned int level, unsigned int logFrequency );
+ virtual void SetLogging( unsigned int statisticsLogOptions,
+ unsigned int timeStampOutput,
+ unsigned int logFrequency );
/**
* @copydoc PerformanceLogger::SetLoggingFrequency()
*/
virtual void EnableLogging( bool enable, ContextId contextId );
-private:
+public: //StatLogInterface
/**
- * Class to hold a stat context
+ * @copydoc StatLogInterface::LogContextStatistics()
*/
- 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
- };
+ virtual void LogContextStatistics( const char* const text );
- /**
- * Helper
- */
- void AddMarkerToLog( const PerformanceMarker& marker, ContextId contextId );
-
- /**
- * 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
- */
- 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
+ * @brief log the marker out to kernel/ DALi log
+ * @param[in] marker performance marker
+ * @param[in] description marker description
*/
- const char* GetMarkerName( MarkerType type ) const;
+ void LogMarker( const PerformanceMarker& marker, const char* const description );
private:
- typedef Dali::Vector< StatContext* > StatContexts;
-
- // The list of stat contexts
- StatContexts mStatContexts;
-
Integration::PlatformAbstraction& mPlatformAbstraction; ///< platform abstraction
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
+ boost::mutex mDataMutex; ///< mutex
+ StatContextManager mStatContextManager; ///< Stat context manager
+ unsigned int mStatisticsLogBitmask; ///< statistics log level
+ unsigned int mPerformanceOutputBitmask; ///< performance marker output
+ bool mLoggingEnabled:1; ///< whether logging update / render to a log is enabled
+ bool mLogFunctionInstalled:1; ///< whether the log function is installed
};
--- /dev/null
+#ifndef __DALI_INTERNAL_ADAPTOR_STATISTICS_STAT_CONTEXT_LOG_INTERFACE_H__
+#define __DALI_INTERNAL_ADAPTOR_STATISTICS_STAT_CONTEXT_LOG_INTERFACE_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.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * @brief Abstract interface used to log statistics data
+ */
+class StatContextLogInterface
+{
+public:
+
+ /**
+ * @brief Used to log statistics out
+ * @param[in] text log the text
+ */
+ virtual void LogContextStatistics( const char* const text) = 0;
+
+
+protected:
+
+ /**
+ * @brief Constructor
+ */
+ StatContextLogInterface()
+ {
+ }
+
+ /**
+ * @brief Virtual Destructor
+ */
+ virtual ~StatContextLogInterface()
+ {
+ }
+
+private:
+
+ // Undefined copy constructor.
+ StatContextLogInterface( const StatContextLogInterface& );
+
+ // Undefined assignment operator.
+ StatContextLogInterface& operator=( const StatContextLogInterface& );
+
+};
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ADAPTOR_STATISTICS_STAT_CONTEXT_LOG_INTERFACE_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 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 "stat-context-manager.h"
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+const char* const UPDATE_CONTEXT_NAME = "Update";
+const char* const RENDER_CONTEXT_NAME = "Render";
+const char* const EVENT_CONTEXT_NAME = "Event";
+const unsigned int DEFAULT_LOG_FREQUENCY = 2;
+}
+
+StatContextManager::StatContextManager( StatContextLogInterface& logInterface )
+: mLogInterface( logInterface ),
+ mNextContextId( 0 ),
+ mStatisticsLogBitmask(0),
+ mLogFrequency( DEFAULT_LOG_FREQUENCY )
+{
+
+ mStatContexts.Reserve(4); // intially reserve enough for 3 internal + 1 custom
+
+ // Add defaults
+ mUpdateStats = AddContext( UPDATE_CONTEXT_NAME, PerformanceMarker::UPDATE );
+ mRenderStats = AddContext( RENDER_CONTEXT_NAME, PerformanceMarker::RENDER );
+ mEventStats = AddContext( EVENT_CONTEXT_NAME, PerformanceMarker::EVENT_PROCESS );
+
+}
+
+StatContextManager::~StatContextManager()
+{
+ for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
+ {
+ StatContext* context = *it;
+ delete context;
+ }
+ mStatContexts.Clear();
+}
+PerformanceInterface::ContextId StatContextManager::AddContext( const char* const name,
+ PerformanceMarker::MarkerFilter type )
+{
+ unsigned int contextId = mNextContextId++;
+
+ DALI_ASSERT_DEBUG( NULL == GetContext( contextId ) );
+
+ // logging enabled by default
+ StatContext* statContext = new StatContext( contextId, name, type, mLogFrequency , mLogInterface );
+
+ // check to see if custom markers are enabled
+ if( ! ( mStatisticsLogBitmask & PerformanceInterface::LOG_CUSTOM_MARKERS ) )
+ {
+ statContext->EnableLogging( false );
+ }
+
+ mStatContexts.PushBack( statContext );
+
+ return contextId;
+}
+
+void StatContextManager::AddInternalMarker( const PerformanceMarker& marker )
+{
+ // log to the stat contexts, can be called from multiple threads so we
+ // protect the data
+ for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
+ {
+ StatContext* context = *it;
+ context->ProcessInternalMarker( marker );
+ }
+}
+
+void StatContextManager::AddCustomMarker( const PerformanceMarker& marker, PerformanceInterface::ContextId contextId )
+{
+ // log to the stat contexts, can be called from multiple threads so we
+ // protect the data
+ StatContext* context = GetContext( contextId );
+ if( context )
+ {
+ context->ProcessCustomMarker( marker );
+ }
+}
+
+void StatContextManager::RemoveContext(PerformanceInterface::ContextId contextId )
+{
+ for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
+ {
+ StatContext* context = *it;
+
+ if( context->GetId() == contextId )
+ {
+ delete context;
+ mStatContexts.Erase( it );
+ return;
+ }
+ }
+}
+
+
+void StatContextManager::EnableLogging( bool enable, PerformanceInterface::ContextId contextId )
+{
+ StatContext* context = GetContext( contextId );
+ if( context )
+ {
+ context->EnableLogging( enable );
+ }
+}
+
+void StatContextManager::SetLoggingLevel( unsigned int statisticsLogOptions, unsigned int logFrequency)
+{
+ mStatisticsLogBitmask = statisticsLogOptions;
+
+ if( mStatisticsLogBitmask == PerformanceInterface::LOG_EVERYTHING )
+ {
+ mStatisticsLogBitmask = 0xFFFFFFFF; // enable everything
+ }
+
+ mLogFrequency = logFrequency;
+
+ // currently uses DALI_LOG_PERFORMANCE_STATS_FREQ environment variable to determine to log frequency
+ // if it's not set it will be zero
+ if( mLogFrequency == 0 )
+ {
+ mLogFrequency = DEFAULT_LOG_FREQUENCY;
+ }
+ EnableLogging( mStatisticsLogBitmask & PerformanceInterface::LOG_UPDATE_RENDER, mUpdateStats );
+ EnableLogging( mStatisticsLogBitmask & PerformanceInterface::LOG_UPDATE_RENDER, mRenderStats );
+ EnableLogging( mStatisticsLogBitmask & PerformanceInterface::LOG_EVENT_PROCESS, mEventStats );
+
+ for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
+ {
+ StatContext* context = *it;
+ context->SetLogFrequency( mLogFrequency );
+ }
+}
+
+void StatContextManager::SetLoggingFrequency( unsigned int logFrequency,
+ PerformanceInterface::ContextId contextId )
+{
+ StatContext* context = GetContext( contextId );
+ if( context )
+ {
+ if( logFrequency == 0 )
+ {
+ logFrequency = DEFAULT_LOG_FREQUENCY;
+ }
+ context->SetLogFrequency( logFrequency );
+ }
+}
+const char* const StatContextManager::GetContextName(PerformanceInterface::ContextId contextId) const
+{
+ StatContext* context = GetContext(contextId);
+ if( context )
+ {
+ return context->GetName();
+ }
+ return "context not found";
+}
+
+const char* const StatContextManager::GetMarkerDescription( PerformanceInterface::MarkerType type, PerformanceInterface::ContextId contextId ) const
+{
+ StatContext* context = GetContext(contextId);
+ if( context )
+ {
+ return context->GetMarkerDescription( type );
+ }
+ return "context not found";
+}
+
+
+StatContext* StatContextManager::GetContext( PerformanceInterface::ContextId contextId ) const
+{
+ for( StatContexts::Iterator it = mStatContexts.Begin(), itEnd = mStatContexts.End(); it != itEnd; ++it )
+ {
+ StatContext* context = *it;
+
+ if( context->GetId() == contextId )
+ {
+ return context;
+ }
+ }
+
+ return NULL;
+}
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
+
+
--- /dev/null
+#ifndef __DALI_INTERNAL_ADAPTOR_STAT_CONTEXT_MANAGER_H__
+#define __DALI_INTERNAL_ADAPTOR_STAT_CONTEXT_MANAGER_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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <base/performance-logging/performance-marker.h>
+#include <base/performance-logging/statistics/stat-context.h>
+#include <base/interfaces/performance-interface.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * Class to manage StatContext objects.
+ *
+ * Contains 3 built in contexts for event, update, render.
+ * The application developer can add more using the PerformanceLogger public API
+ *
+ * Example output of 4 contexts ( event, update, render and a custom one):
+ *
+ * Event, min 0.04 ms, max 5.27 ms, total (0.1 secs), avg 0.28 ms, std dev 0.73 ms
+ * Update, min 0.29 ms, max 0.91 ms, total (0.5 secs), avg 0.68 ms, std dev 0.15 ms
+ * Render, min 0.33 ms, max 0.97 ms, total (0.6 secs), avg 0.73 ms, std dev 0.17 ms
+ * MyAppTask, min 76.55 ms, max 76.55 ms, total (0.1 secs), avg 76.55 ms, std dev 0.00 ms (CUSTOM CONTEXT)
+ *
+ */
+class StatContextManager
+{
+
+public:
+
+ /**
+ * @brief Constructor
+ * @param[in] logInterface interface to log statistics to
+ */
+ StatContextManager( StatContextLogInterface& logInterface );
+
+ /**
+ * @brief destructor, not intended as a bass class
+ */
+ ~StatContextManager();
+
+ /**
+ * @brief Add a context
+ * @param[in] name Name of the context to print in console
+ * @param[in] type the type of events to filter ( e.g. event, update, render or custom)
+ * @return The ID to give the context
+ */
+ PerformanceInterface::ContextId AddContext( const char* const name, PerformanceMarker::MarkerFilter type );
+
+ /**
+ * @brief Remove a context
+ * @param[in] contextId id of the context to remove
+ */
+ void RemoveContext(PerformanceInterface::ContextId contextId );
+
+ /**
+ * @brief Add an internal marker (e.g. v-sync, update, render markers)
+ * @param[in] marker the marker to add
+ */
+ void AddInternalMarker( const PerformanceMarker& marker );
+
+ /**
+ * @brief Add a custom marker defined by the application
+ * @param[in] marker the marker to add
+ * @param[in] contextId the context the custom marker is designed for
+ */
+ void AddCustomMarker( const PerformanceMarker& marker , PerformanceInterface::ContextId contextId );
+
+ /**
+ * @brief Get the nane of a context
+ * @param[in] contextId id of the context to get the name
+ * @return context name
+ */
+ const char* const GetContextName( PerformanceInterface::ContextId contextId ) const;
+
+ /**
+ * @brief Get the full description of a marker for this context
+ * @param[in] type marker type, for a customer marker this will be either START or END
+ * @param[in] contextId id of the context to get the name
+ * @return marker description in relation to this context
+ */
+ const char* const GetMarkerDescription( PerformanceInterface::MarkerType type, PerformanceInterface::ContextId contextId ) const;
+
+
+ /**
+ * @brief enable / disable logging for a context
+ * @param[in] enable whether to enable logging
+ * @param[in] contextId the context to configure
+ */
+ void EnableLogging( bool enable, PerformanceInterface::ContextId contextId );
+
+ /**
+ * @brief set global logging level and frequency.
+ * @param[in] statisticsLogOptions log options
+ * @param[in] logFrequency frequency in seconds
+ */
+ void SetLoggingLevel( unsigned int statisticsLogOptions, unsigned int logFrequency);
+
+ /**
+ * @brief Set the frequency of logging for an individual context
+ * @param[in] logFrequency log frequency in seconds
+ * @param[in] contextId the context to configure
+ */
+ void SetLoggingFrequency( unsigned int logFrequency, PerformanceInterface::ContextId contextId );
+
+ private:
+
+ typedef Dali::Vector< StatContext* > StatContexts;
+
+ /**
+ * @brief helper
+ * @param[in] contextId the context to get
+ * @return context
+ */
+ StatContext* GetContext( PerformanceInterface::ContextId contextId ) const;
+
+ StatContexts mStatContexts; ///< The list of stat contexts
+ StatContextLogInterface& mLogInterface; ///< Log interface
+
+ PerformanceInterface::ContextId mNextContextId; ///< The next valid context ID
+
+ // Some defaults contexts
+ PerformanceInterface::ContextId mUpdateStats; ///< update time statistics
+ PerformanceInterface::ContextId mRenderStats; ///< render time statistics
+ PerformanceInterface::ContextId mEventStats; ///< event time statistics
+
+ unsigned int mStatisticsLogBitmask; ///< statistics log bitmask
+ unsigned int mLogFrequency; ///< log frequency
+};
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ADAPTOR_STAT_CONTEXT_MANAGER_H__
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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 "stat-context.h"
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/platform-abstraction.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+#define TIME_FMT "%0.2f ms" // 2 decimal places, e.g. 5.34 ms
+#define TOTAL_TIME_FMT "%0.1f secs" // 1 decimal place, e.g. 4.5 seconds
+
+namespace
+{
+const unsigned int MILLISECONDS_PER_SECOND = 1000; ///< 1000 milliseconds per second
+const char* const UNKNOWN_CONTEXT_NAME = "UNKNOWN_CONTEXT_NAME";
+const unsigned int MICROSECONDS_PER_SECOND = 1000000; ///< 1000000 microseconds per second
+const unsigned int CONTEXT_LOG_SIZE = 120;
+
+}
+
+StatContext::StatContext( unsigned int id,
+ const char* const contextName,
+ PerformanceMarker::MarkerFilter contextType,
+ unsigned int logFrequencySeconds,
+ StatContextLogInterface& logInterface )
+: mInitialMarker(PerformanceInterface::VSYNC),
+ mName( contextName ),
+ mLogInterface( logInterface ),
+ mNamePlusStart( std::string(contextName) + "_START" ),
+ mNamePlusEnd( std::string(contextName) + "_END" ),
+ mId( id ),
+ mLogFrequencyMicroseconds( logFrequencySeconds * MICROSECONDS_PER_SECOND ),
+ mFilterType( contextType ),
+ mLoggingEnabled( true ),
+ mInitialMarkerSet( false )
+{
+ mTempLogBuffer = new char[ CONTEXT_LOG_SIZE ];
+}
+
+StatContext::~StatContext()
+{
+ delete []mTempLogBuffer;
+}
+unsigned int StatContext::GetId() const
+{
+ return mId;
+}
+
+const char* const StatContext::GetName() const
+{
+ return mName;
+}
+
+const char* const StatContext::GetMarkerDescription( PerformanceInterface::MarkerType type ) const
+{
+ if( type == PerformanceInterface::START )
+ {
+ return mNamePlusStart.c_str();
+ }
+ else if( type == PerformanceInterface::END )
+ {
+ return mNamePlusEnd.c_str();
+ }
+ return UNKNOWN_CONTEXT_NAME;
+}
+void StatContext::SetLogFrequency( unsigned int logFrequencySeconds )
+{
+ mLogFrequencyMicroseconds = logFrequencySeconds * MICROSECONDS_PER_SECOND;
+}
+
+void StatContext::EnableLogging( bool enableLogging )
+{
+ mLoggingEnabled = enableLogging;
+}
+
+void StatContext::ProcessCustomMarker( const PerformanceMarker& marker )
+{
+ // this marker has come from the application PerformanceLogger API
+ RecordMarker( marker);
+}
+
+void StatContext::ProcessInternalMarker( const PerformanceMarker& marker )
+{
+ // this marker has come from DALi internal not the application
+ // see if this context is for update, render or event
+ if( marker.IsFilterEnabled( mFilterType ))
+ {
+ RecordMarker( marker );
+ }
+ // V_SYNC is always processed
+ if( marker.GetType() == PerformanceInterface::VSYNC )
+ {
+ FrameTick( marker );
+ }
+}
+
+void StatContext::RecordMarker( const PerformanceMarker& marker )
+{
+ if( marker.GetEventType() == PerformanceMarker::START_TIMED_EVENT )
+ {
+ mStats.StartTime( marker.GetTimeStamp() );
+ }
+ else if( marker.GetEventType() == PerformanceMarker::END_TIMED_EVENT )
+ {
+ mStats.EndTime( marker.GetTimeStamp() );
+ }
+}
+
+void StatContext::FrameTick( const PerformanceMarker& marker )
+{
+ // wait until we've got some data
+ if( ! mInitialMarkerSet )
+ {
+ mInitialMarker = marker;
+ mInitialMarkerSet = true;
+ return;
+ }
+ // log out every mLogFrequency.
+ // check difference between first and last frame
+ unsigned int microseconds = PerformanceMarker::MicrosecondDiff( mInitialMarker, marker );
+
+ if( microseconds < mLogFrequencyMicroseconds )
+ {
+ return;
+ }
+
+ if( mLoggingEnabled )
+ {
+ LogMarker();
+ }
+ mStats.Reset(); // reset data for statistics
+ mInitialMarkerSet = false; // need to restart the timer
+
+}
+
+void StatContext::LogMarker()
+{
+ float mean, standardDeviation;
+ mStats.CalculateMean( mean, standardDeviation );
+
+ snprintf( mTempLogBuffer, CONTEXT_LOG_SIZE, "%s, min " TIME_FMT ", max " TIME_FMT ", total (" TOTAL_TIME_FMT "), avg " TIME_FMT ", std dev " TIME_FMT "\n",
+ mName ? mName : UNKNOWN_CONTEXT_NAME,
+ mStats.GetMinTime() * MILLISECONDS_PER_SECOND,
+ mStats.GetMaxTime() * MILLISECONDS_PER_SECOND,
+ mStats.GetTotalTime(),
+ mean * MILLISECONDS_PER_SECOND,
+ standardDeviation * MILLISECONDS_PER_SECOND );
+
+ mLogInterface.LogContextStatistics( mTempLogBuffer );
+
+}
+
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_INTERNAL_ADAPTOR_STAT_CONTEXT_H__
+#define __DALI_INTERNAL_ADAPTOR_STAT_CONTEXT_H__
+
+/*
+ * Copyright (c) 2015 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <base/performance-logging/performance-marker.h>
+#include <base/performance-logging/frame-time-stats.h>
+#include <base/interfaces/performance-interface.h>
+#include <base/performance-logging/statistics/stat-context-log-interface.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+/**
+ * Stores and prints statistics for a particular logging context.
+ *
+ */
+class StatContext
+{
+
+public:
+
+ /**
+ * @brief Constructor
+ *
+ * @param[in] id The ID to give the context
+ * @param[in] contextName Name of the context to print in console
+ * @param[in] contextType the type of events to filter ( e.g. event, update, render or custom)
+ * @param[in] logFrequencySeconds frequency to log in seconds
+ * @param[in] logInterface interface to log out to
+ *
+ */
+ StatContext( unsigned int id,
+ const char* const contextName,
+ PerformanceMarker::MarkerFilter contextType,
+ unsigned int logFrequencySeconds,
+ StatContextLogInterface& logInterface );
+
+
+ /**
+ * @brief Non-virtual destructor, not intended as a base class
+ */
+ ~StatContext();
+
+ /**
+ * @return Return the context ID
+ */
+ unsigned int GetId() const;
+
+ /**
+ * @return the context name
+ */
+ const char* const GetName() const;
+
+ /**
+ *
+ * For logging we want to output the name of the context with either
+ * START / END appended to the end. E.g. MY_MARKER_START
+ * @param[in] type marker type, for a customer marker this will be either START or END
+ * @return the full description for a marker
+ */
+ const char* const GetMarkerDescription( PerformanceInterface::MarkerType type ) const;
+
+ /**
+ * @brief Set the frequency for logging
+ *
+ * @param[in] logFrequencySeconds The log frequency to set in seconds
+ */
+ void SetLogFrequency( unsigned int logFrequencySeconds );
+
+ /**
+ * @brief enable/disable logging
+ *
+ * @param[in] enableLogging Flag to spePerformancecify enabling/disabling
+ */
+ void EnableLogging( bool enableLogging );
+
+ /**
+ * @brief Process a custom marker from the application
+ *
+ * @param[in] marker The marker to log
+ */
+ void ProcessCustomMarker( const PerformanceMarker& marker );
+
+ /**
+ * @brief Process a internal marker from DALi (V_SYNC/ UPDATE /RENDER/ EVENT )
+ *
+ * @param[in] marker The marker to log
+ */
+ void ProcessInternalMarker( const PerformanceMarker& marker );
+
+ private:
+
+ /**
+ * @brief Record marker
+ *
+ * @param[in] marker to record
+ */
+ void RecordMarker( const PerformanceMarker& marker );
+
+ /**
+ * @brief Called when V-SYNC occurs to indicate a frame tick
+ * @param[in] marker the marker containing a v-sync
+ */
+ void FrameTick( const PerformanceMarker& marker );
+
+ /**
+ * @brief Helper to print to console
+ */
+ void LogMarker();
+
+
+ private:
+
+ StatContext(); ///< undefined default constructor
+
+ StatContext( const StatContext& ); ///< undefined copy constructor
+
+ StatContext& operator=( const StatContext& ); ///< undefined assignment operator
+
+ private:
+
+ PerformanceMarker mInitialMarker; ///< Used to store initial time
+ FrameTimeStats mStats; ///< Frame time stats to accumulate
+ const char* const mName; ///< Name of the context
+ char* mTempLogBuffer; ///< Temporary log buffer
+ StatContextLogInterface& mLogInterface; ///< Log interface
+ const std::string mNamePlusStart; ///< Name of the context + _START
+ const std::string mNamePlusEnd; ///< Name of the context + _END
+ unsigned int mId; ///< The ID of the context
+ unsigned int mLogFrequencyMicroseconds; ///< if logging is enabled, what frequency to log out at in micro-seconds
+ PerformanceMarker::MarkerFilter mFilterType; ///< type of events the context is filtering
+ bool mLoggingEnabled:1; ///< Whether to print the log for this context or not
+ bool mInitialMarkerSet:1; ///< Whether the initial marker has been set
+
+};
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
+
+#endif
// get logging options
unsigned int logFrameRateFrequency = GetIntegerEnvironmentVariable( DALI_ENV_FPS_TRACKING, 0 );
unsigned int logupdateStatusFrequency = GetIntegerEnvironmentVariable( DALI_ENV_UPDATE_STATUS_INTERVAL, 0 );
- unsigned int logPerformanceLevel = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE, 0 );
+ unsigned int logPerformanceStats = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE_STATS, 0 );
+ unsigned int logPerformanceStatsFrequency = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE_STATS_FREQUENCY, 0 );
+ unsigned int performanceTimeStampOutput= GetIntegerEnvironmentVariable( DALI_ENV_PERFORMANCE_TIMESTAMP_OUTPUT, 0 );
+
+
unsigned int logPanGesture = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PAN_GESTURE, 0 );
// all threads here (event, update, and render) will send their logs to SLP Platform's LogMessage handler.
Dali::Integration::Log::LogFunction logFunction(Dali::SlpPlatform::LogMessage);
- mEnvironmentOptions.SetLogOptions( logFunction, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceLevel, logPanGesture );
+ mEnvironmentOptions.SetLogOptions( logFunction, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceStats, logPerformanceStatsFrequency, performanceTimeStampOutput, logPanGesture );
int predictionMode;
if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_MODE, predictionMode) )
// Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
// files automatically.
- if( mEnvironmentOptions.GetPerformanceLoggingLevel() > 0 )
+ if( mEnvironmentOptions.PerformanceServerRequired() )
{
mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, mEnvironmentOptions );
}