// $Id: ITAStopWatch.cpp 3923 2015-01-07 16:09:21Z pelzer $ #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 == NULL) 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(); /* DEBUG: printf("%s: Measured start/stop latency: %0.3f ns\n", __FUNCTION__, _dStartStopLatency * 1000000000); */ 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(); } bool ITAStopWatch::started() const { return m_bStarted; } unsigned int ITAStopWatch::cycles() const { m_csReadWrite.enter(); unsigned int uiResult = m_uiCycles; m_csReadWrite.leave(); return uiResult; } /* void ITAStopWatch::setMaxCycles(unsigned int uiMaxCycles) { m_uiMaxCycles = uiMaxCycles; } */ 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 -1; } double dResult = m_dSum / m_uiCycles; m_csReadWrite.leave(); return dResult; } return -1; } double ITAStopWatch::variance() const { if (m_csReadWrite.tryenter() == true) { if (m_uiCycles == 0) { m_csReadWrite.leave(); return -1; } // 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 -1; } 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) { if (dTimeSeconds < 1e-6) return std::string(std::to_string( long double( dTimeSeconds / 1e-9) ) + "us"); else if (dTimeSeconds < 1e-3) return std::string(std::to_string( long double( dTimeSeconds / 1e-6)) + "ns"); else if (dTimeSeconds < 1e-0) return std::string(std::to_string( long double( dTimeSeconds / 1e-3)) + "ms"); else return std::string(std::to_string( long double( dTimeSeconds)) + "s"); }; 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(); } 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; }