#include #include #include #include #include #include bool ITAStopWatch::m_bInstanceCreated = false; double ITAStopWatch::m_dStartStopLatency = 0; ITAStopWatch::ITAStopWatch() : m_pClock( ITAClock::getDefaultClock() ) { // Falls dies die erste Stopwatch ist die erzeugt wird: Latenz messen if( !m_bInstanceCreated ) { ITACriticalSection cs; cs.enter(); start(); stop(); reset(); for( unsigned int i = 0; i < 100; i++ ) { start(); stop(); } cs.leave(); m_dStartStopLatency = minimum(); /* DEBUG: printf("%s: Measured start/stop latency: %0.3f ns\n", __FUNCTION__, _dStartStopLatency * 1000000000); */ m_bInstanceCreated = true; } reset(); } ITAStopWatch::ITAStopWatch( ITAClock* pClock ) : m_pClock( pClock ) { if( !pClock ) ITA_EXCEPT1( INVALID_PARAMETER, "Clock must not be NULL" ); // Falls dies die erste Stopwatch ist die erzeugt wird: Latenz messen if( !m_bInstanceCreated ) { ITACriticalSection cs; cs.enter(); start(); stop(); reset(); for( unsigned int i = 0; i < 100; i++ ) { start(); stop(); } cs.leave(); m_dStartStopLatency = minimum(); m_bInstanceCreated = true; } reset(); } void ITAStopWatch::reset() { m_csReadWrite.enter(); m_uiCycles = 0; m_dSum = m_dSquareSum = 0; m_dMin = DBL_MAX; m_dMax = 0; m_bStarted = false; m_csReadWrite.leave(); } void ITAStopWatch::start() { m_dStart = m_pClock->getTime(); m_bStarted = true; } bool ITAStopWatch::started() const { return m_bStarted; } double ITAStopWatch::stop() { m_dStop = m_pClock->getTime(); double t = m_dStop - m_dStart - m_dStartStopLatency; m_csReadWrite.enter(); m_dMin = ( std::min )( m_dMin, t ); m_dMax = ( std::max )( m_dMax, t ); m_dSum += t; m_dSquareSum += ( t*t ); m_uiCycles++; m_bStarted = false; m_csReadWrite.leave(); return t; } unsigned int ITAStopWatch::cycles() const { m_csReadWrite.enter(); unsigned int uiResult = m_uiCycles; m_csReadWrite.leave(); return uiResult; } double ITAStopWatch::minimum() const { return ( m_uiCycles == 0 ? 0 : m_dMin ); } double ITAStopWatch::maximum() const { return m_dMax; } double ITAStopWatch::mean() const { if( m_csReadWrite.tryenter() == true ) { if( m_uiCycles == 0 ) { m_csReadWrite.leave(); return 0; } double dResult = m_dSum / m_uiCycles; m_csReadWrite.leave(); return dResult; } return 0; } double ITAStopWatch::variance() const { if( m_csReadWrite.tryenter() == true ) { if( m_uiCycles == 0 ) { m_csReadWrite.leave(); return 0; } // Formel: sigma = E(X^2) - E(X)^2 double x = ( m_dSum / m_uiCycles ); double dResult = ( m_dSquareSum / m_uiCycles ) - ( x*x ); m_csReadWrite.leave(); return dResult; } return 0; } double ITAStopWatch::std_deviation() const { return sqrt( variance() ); } double ITAStopWatch::selftest() { ITAStopWatch sw; sw.start(); sw.stop(); sw.reset(); for( int i = 0; i < 1000; i++ ) { sw.start(); sw.stop(); } return sw.mean(); } std::string TimeToString( double dTimeSeconds ) { std::stringstream ss; if( dTimeSeconds < 1e-6 ) ss << dTimeSeconds / 1e-9 << "us"; else if( dTimeSeconds < 1e-3 ) ss << dTimeSeconds / 1e-6 << "ns"; else if( dTimeSeconds < 1e-0 ) ss << dTimeSeconds / 1e-3 << "ms"; else ss << dTimeSeconds << "s"; return ss.str(); }; std::string ITAStopWatch::ToString() const { std::ostringstream ss; ss << "avg=" << TimeToString( mean() ) << ", "; ss << "stddev=" << TimeToString( std_deviation() ) << ", "; ss << "min=" << TimeToString( minimum() ) << ", "; ss << "max=" << TimeToString( maximum() ) << ", "; ss << "cycles=" << cycles(); return ss.str(); }