From 8d75780f92f5e8c780ea450e455d0b61ad986fa4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 28 Mar 2012 01:45:51 +0200 Subject: [PATCH] PEP 418: I'm not quite sure, but it looks like QueryPerformanceCounter() *is* monotonic --- pep-0418.txt | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/pep-0418.txt b/pep-0418.txt index 0afc48d36..67409f47d 100644 --- a/pep-0418.txt +++ b/pep-0418.txt @@ -62,7 +62,7 @@ The system time is the "wall clock". It can be set manually by the system administrator or automatically by a NTP daemon. It can jump backward and forward, and is not monotonic. -It is avaialble on all platforms and cannot fail. +It is available on all platforms and cannot fail. Pseudo-code:: @@ -104,30 +104,47 @@ Pseudo-code:: if os.name == 'nt': if hasattr(time, '_GetTickCount64'): - monotonic = _time.GetTickCount64 + _get_tick_count = _time.GetTickCount64 else: - def monotonic(): + def _get_tick_count(): ticks = _time.GetTickCount() - if ticks < monotonic.last: + if ticks < _get_tick_count.last: # Integer overflow detected - monotonic.delta += 2**32 - monotonic.last = ticks - return ticks + monotonic.delta - monotonic.last = 0 - monotonic.delta = 0 - if os.name == 'mac': + _get_tick_count.delta += 2**32 + _get_tick_count.last = ticks + return ticks + _get_tick_count.delta + _get_tick_count.last = 0 + _get_tick_count.delta = 0 + + def monotonic(): + if monotonic.use_performance_counter: + try: + return _time.QueryPerformanceCounter() + except OSError: + # QueryPerformanceFrequency() may fail, if the installed + # hardware does not support a high-resolution performance + # counter for example + monotonic.use_performance_counter = False + # Fallback to GetTickCount/GetTickCount64 which has + # a lower resolution + return _get_tick_count() + monotonic.use_performance_counter = True + + elif os.name == 'mac': def monotonic(): if monotonic.factor is None: factor = _time.mach_timebase_info() monotonic.factor = timebase[0] / timebase[1] return _time.mach_absolute_time() * monotonic.factor monotonic.factor = None + elif hasattr(time, "clock_gettime") and hasattr(time, "CLOCK_MONOTONIC"): def monotonic(): if monotonic.use_monotonic_raw: try: return time.clock_gettime(time.CLOCK_MONOTONIC_RAW) except OSError: + # CLOCK_MONOTONIC_RAW requires a Linux kernel >= 2.6.28 monotonic.use_monotonic_raw = False return time.clock_gettime(time.CLOCK_MONOTONIC) monotonic.use_monotonic_raw = hasattr(time, "CLOCK_MONOTONIC_RAW") @@ -320,7 +337,7 @@ had a bug (see `KB896256 `_): on a multiprocessor computer, QueryPerformanceCounter() returned a different value for each processor. -QueryPerformanceCounter() is not monotonic. +QueryPerformanceCounter() is monotonic. QueryPerformanceFrequency() fails if the installed hardware does not support a high-resolution performance counter. @@ -395,4 +412,8 @@ Links `_ * `Windows: Game Timing and Multicore Processors `_ + * `Implement a Continuously Updating, High-Resolution Time Provider for Windows + `_ + * `Perl: Time::HiRes + `_