1 /* 2 * Created by Phil on 05/08/2013. 3 * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 9 #include "catch_timer.h" 10 11 #include <chrono> 12 13 static const uint64_t nanosecondsInSecond = 1000000000; 14 15 namespace Catch { 16 getCurrentNanosecondsSinceEpoch()17 auto getCurrentNanosecondsSinceEpoch() -> uint64_t { 18 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); 19 } 20 21 namespace { estimateClockResolution()22 auto estimateClockResolution() -> uint64_t { 23 uint64_t sum = 0; 24 static const uint64_t iterations = 1000000; 25 26 auto startTime = getCurrentNanosecondsSinceEpoch(); 27 28 for( std::size_t i = 0; i < iterations; ++i ) { 29 30 uint64_t ticks; 31 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); 32 do { 33 ticks = getCurrentNanosecondsSinceEpoch(); 34 } while( ticks == baseTicks ); 35 36 auto delta = ticks - baseTicks; 37 sum += delta; 38 39 // If we have been calibrating for over 3 seconds -- the clock 40 // is terrible and we should move on. 41 // TBD: How to signal that the measured resolution is probably wrong? 42 if (ticks > startTime + 3 * nanosecondsInSecond) { 43 return sum / ( i + 1u ); 44 } 45 } 46 47 // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers 48 // - and potentially do more iterations if there's a high variance. 49 return sum/iterations; 50 } 51 } getEstimatedClockResolution()52 auto getEstimatedClockResolution() -> uint64_t { 53 static auto s_resolution = estimateClockResolution(); 54 return s_resolution; 55 } 56 start()57 void Timer::start() { 58 m_nanoseconds = getCurrentNanosecondsSinceEpoch(); 59 } getElapsedNanoseconds() const60 auto Timer::getElapsedNanoseconds() const -> uint64_t { 61 return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; 62 } getElapsedMicroseconds() const63 auto Timer::getElapsedMicroseconds() const -> uint64_t { 64 return getElapsedNanoseconds()/1000; 65 } getElapsedMilliseconds() const66 auto Timer::getElapsedMilliseconds() const -> unsigned int { 67 return static_cast<unsigned int>(getElapsedMicroseconds()/1000); 68 } getElapsedSeconds() const69 auto Timer::getElapsedSeconds() const -> double { 70 return getElapsedMicroseconds()/1000000.0; 71 } 72 73 74 } // namespace Catch 75