 Chromium Code Reviews
 Chromium Code Reviews Issue 1452843003:
  Several Tick counter improvements try #2."  (Closed) 
  Base URL: https://chromium.googlesource.com/external/webrtc.git@master
    
  
    Issue 1452843003:
  Several Tick counter improvements try #2."  (Closed) 
  Base URL: https://chromium.googlesource.com/external/webrtc.git@master| Index: webrtc/system_wrappers/source/tick_util.cc | 
| diff --git a/webrtc/system_wrappers/source/tick_util.cc b/webrtc/system_wrappers/source/tick_util.cc | 
| index bc8fcfe91b3f90b22fa9283ab77c79893cbf1528..cae817dc55b199c22d35afe8a013d9cc98e631db 100644 | 
| --- a/webrtc/system_wrappers/source/tick_util.cc | 
| +++ b/webrtc/system_wrappers/source/tick_util.cc | 
| @@ -17,6 +17,71 @@ namespace webrtc { | 
| bool TickTime::use_fake_clock_ = false; | 
| int64_t TickTime::fake_ticks_ = 0; | 
| +int64_t TickTime::MillisecondTimestamp() { | 
| + return TicksToMilliseconds(TickTime::Now().Ticks()); | 
| +} | 
| + | 
| +int64_t TickTime::MicrosecondTimestamp() { | 
| + return TicksToMicroseconds(TickTime::Now().Ticks()); | 
| +} | 
| + | 
| +int64_t TickTime::MillisecondsToTicks(const int64_t ms) { | 
| +#if _WIN32 | 
| + return ms; | 
| +#elif defined(WEBRTC_LINUX) | 
| + return ms * 1000000LL; | 
| +#elif defined(WEBRTC_MAC) | 
| + // TODO(pbos): Fix unsafe use of static locals. | 
| + static double timebase_from_millisecond_fract = 0.0; | 
| + if (timebase_from_millisecond_fract == 0.0) { | 
| + mach_timebase_info_data_t timebase; | 
| + (void)mach_timebase_info(&timebase); | 
| + timebase_from_millisecond_fract = (timebase.denom * 1e6) / timebase.numer; | 
| + } | 
| + return ms * timebase_from_millisecond_fract; | 
| +#else | 
| + return ms * 1000LL; | 
| +#endif | 
| +} | 
| + | 
| +int64_t TickTime::TicksToMilliseconds(const int64_t ticks) { | 
| +#if _WIN32 | 
| + return ticks; | 
| +#elif defined(WEBRTC_LINUX) | 
| + return ticks / 1000000LL; | 
| +#elif defined(WEBRTC_MAC) | 
| + // TODO(pbos): Fix unsafe use of static locals. | 
| + static double timebase_microsecond_fract = 0.0; | 
| + if (timebase_microsecond_fract == 0.0) { | 
| + mach_timebase_info_data_t timebase; | 
| + (void)mach_timebase_info(&timebase); | 
| + timebase_microsecond_fract = timebase.numer / (timebase.denom * 1e6); | 
| + } | 
| + return ticks * timebase_microsecond_fract; | 
| +#else | 
| + return ticks; | 
| +#endif | 
| +} | 
| + | 
| +int64_t TickTime::TicksToMicroseconds(const int64_t ticks) { | 
| +#if _WIN32 | 
| + return ticks * 1000LL; | 
| +#elif defined(WEBRTC_LINUX) | 
| + return ticks / 1000LL; | 
| +#elif defined(WEBRTC_MAC) | 
| + // TODO(pbos): Fix unsafe use of static locals. | 
| + static double timebase_microsecond_fract = 0.0; | 
| + if (timebase_microsecond_fract == 0.0) { | 
| + mach_timebase_info_data_t timebase; | 
| + (void)mach_timebase_info(&timebase); | 
| + timebase_microsecond_fract = timebase.numer / (timebase.denom * 1e3); | 
| + } | 
| + return ticks * timebase_microsecond_fract; | 
| +#else | 
| + return ticks; | 
| +#endif | 
| +} | 
| + | 
| void TickTime::UseFakeClock(int64_t start_millisecond) { | 
| use_fake_clock_ = true; | 
| fake_ticks_ = MillisecondsToTicks(start_millisecond); | 
| @@ -27,20 +92,14 @@ void TickTime::AdvanceFakeClock(int64_t milliseconds) { | 
| fake_ticks_ += MillisecondsToTicks(milliseconds); | 
| } | 
| +// Gets the native system tick count. The actual unit, resolution, and epoch | 
| +// varies by platform: | 
| +// Windows: Milliseconds of uptime with rollover count in the upper 32-bits. | 
| +// Linux/Android: Nanoseconds since the Unix epoch. | 
| +// Mach (Mac/iOS): "absolute" time since first call. | 
| +// Unknown POSIX: Microseconds since the Unix epoch. | 
| int64_t TickTime::QueryOsForTicks() { | 
| - TickTime result; | 
| #if _WIN32 | 
| - // TODO(wu): Remove QueryPerformanceCounter implementation. | 
| -#ifdef USE_QUERY_PERFORMANCE_COUNTER | 
| - // QueryPerformanceCounter returns the value from the TSC which is | 
| - // incremented at the CPU frequency. The algorithm used requires | 
| - // the CPU frequency to be constant. Technology like speed stepping | 
| - // which has variable CPU frequency will therefore yield unpredictable, | 
| - // incorrect time estimations. | 
| - LARGE_INTEGER qpcnt; | 
| - QueryPerformanceCounter(&qpcnt); | 
| - result.ticks_ = qpcnt.QuadPart; | 
| -#else | 
| static volatile LONG last_time_get_time = 0; | 
| static volatile int64_t num_wrap_time_get_time = 0; | 
| volatile LONG* last_time_get_time_ptr = &last_time_get_time; | 
| @@ -53,11 +112,11 @@ int64_t TickTime::QueryOsForTicks() { | 
| // 0x0fffffff ~3.1 days, the code will not take that long to execute | 
| // so it must have been a wrap around. | 
| if (old > 0xf0000000 && now < 0x0fffffff) { | 
| + // TODO(pbos): Fix unsafe use of static locals. | 
| num_wrap_time_get_time++; | 
| } | 
| } | 
| - result.ticks_ = now + (num_wrap_time_get_time << 32); | 
| -#endif | 
| + return now + (num_wrap_time_get_time << 32); | 
| #elif defined(WEBRTC_LINUX) | 
| struct timespec ts; | 
| // TODO(wu): Remove CLOCK_REALTIME implementation. | 
| @@ -66,33 +125,24 @@ int64_t TickTime::QueryOsForTicks() { | 
| #else | 
| clock_gettime(CLOCK_MONOTONIC, &ts); | 
| #endif | 
| - result.ticks_ = 1000000000LL * static_cast<int64_t>(ts.tv_sec) + | 
| - static_cast<int64_t>(ts.tv_nsec); | 
| + return 1000000000LL * ts.tv_sec + ts.tv_nsec; | 
| #elif defined(WEBRTC_MAC) | 
| - static mach_timebase_info_data_t timebase; | 
| - if (timebase.denom == 0) { | 
| - // Get the timebase if this is the first time we run. | 
| - // Recommended by Apple's QA1398. | 
| - kern_return_t retval = mach_timebase_info(&timebase); | 
| - if (retval != KERN_SUCCESS) { | 
| - // TODO(wu): Implement RTC_CHECK for all the platforms. Then replace this | 
| - // with a RTC_CHECK_EQ(retval, KERN_SUCCESS); | 
| -#ifndef WEBRTC_IOS | 
| - asm("int3"); | 
| -#else | 
| - __builtin_trap(); | 
| -#endif // WEBRTC_IOS | 
| - } | 
| + // Return absolute time as an offset from the first call to this function, so | 
| + // that we can do floating-point (double) operations on it without losing | 
| + // precision. This holds true until the elapsed time is ~11 days, | 
| + // at which point we'll start to lose some precision, though not enough to | 
| + // matter for millisecond accuracy for another couple years after that. | 
| + // TODO(pbos): Fix unsafe use of static locals. | 
| + static uint64_t timebase_start = 0; | 
| + if (timebase_start == 0) { | 
| + timebase_start = mach_absolute_time(); | 
| } | 
| - // Use timebase to convert absolute time tick units into nanoseconds. | 
| - result.ticks_ = mach_absolute_time() * timebase.numer / timebase.denom; | 
| + return mach_absolute_time() - timebase_start; | 
| 
tommi
2016/01/23 14:09:41
There's a bug here which will affect cases where R
 | 
| #else | 
| struct timeval tv; | 
| gettimeofday(&tv, NULL); | 
| - result.ticks_ = 1000000LL * static_cast<int64_t>(tv.tv_sec) + | 
| - static_cast<int64_t>(tv.tv_usec); | 
| + return 1000000LL * tv.tv_sec + tv.tv_usec; | 
| #endif | 
| - return result.ticks_; | 
| } | 
| } // namespace webrtc |