diff --git a/pep-0418.txt b/pep-0418.txt index 11efa085c..fd55f25ef 100644 --- a/pep-0418.txt +++ b/pep-0418.txt @@ -1,5 +1,5 @@ PEP: 418 -Title: Add monotonic and high-resolution time functions +Title: Add steady and high-resolution time functions Version: $Revision$ Last-Modified: $Date$ Author: Victor Stinner @@ -13,7 +13,7 @@ Python-Version: 3.3 Abstract ======== -Add time.monotonic(), time.highres(), time.get_clock_info(name) functions to +Add time.steady(), time.highres(), time.get_clock_info(name) functions to Python 3.3. @@ -26,7 +26,7 @@ Use cases: a wall clock): use system clock, i.e. time.time() or datetime.datetime.now(). * Benchmark, profiling: time.highres(). -* Event scheduler, timeout: time.monotonic(). +* Event scheduler, timeout: time.steady(). Functions @@ -36,8 +36,7 @@ To fulfill the use cases, the functions' properties are: * time.time(): system clock, "wall clock". * time.highres(): clock with the best accuracy. -* time.monotonic(): monotonic clock, or system clock if no monotonic - clock is available +* time.steady(): steady clock, should be monotonic * time.get_clock_info(name): get information on the specified time function @@ -79,15 +78,14 @@ Pseudo-code [#pseudo]_:: return _time.time() -time.monotonic() ----------------- +time.steady() +------------- -Monotonic clock, or system clock if the platform does not provide a monotonic -clock (e.g. on GNU/Hurd). Its rate is as steady as possible. Its rate may be -adjusted by NTP. The reference point of the returned value is undefined so -only the difference of consecutive calls is valid. +Steady clock. Use a monotonic clock, or falls back to the system clock. Its +rate may be adjusted by NTP. The reference point of the returned value is +undefined so only the difference of consecutive calls is valid. -Use time.get_clock_info('monotonic')['is_monotonic'] to check if the clock +Use time.get_clock_info('steady')['is_monotonic'] to check if the clock monotonic or not. The elapsed time may or may not include time the system spends in @@ -98,60 +96,60 @@ Pseudo-code [#pseudo]_:: if os.name == 'nt': # GetTickCount64() requires Windows Vista, Server 2008 or later if hasattr(time, '_GetTickCount64'): - def monotonic(): + def steady(): return _time.GetTickCount64() else: - def monotonic(): + def steady(): ticks = _time.GetTickCount() - if ticks < monotonic.last: + if ticks < steady.last: # Integer overflow detected - monotonic.delta += 2**32 - monotonic.last = ticks - return ticks + monotonic.delta - monotonic.last = 0 - monotonic.delta = 0 + steady.delta += 2**32 + steady.last = ticks + return ticks + steady.delta + steady.last = 0 + steady.delta = 0 elif os.name == 'mac': - def monotonic(): - if monotonic.factor is None: + def steady(): + if steady.factor is None: factor = _time.mach_timebase_info() - monotonic.factor = timebase[0] / timebase[1] - return _time.mach_absolute_time() * monotonic.factor - monotonic.factor = None + steady.factor = timebase[0] / timebase[1] + return _time.mach_absolute_time() * steady.factor + steady.factor = None elif os.name.startswith('sunos'): - def monotonic(): - if monotonic.use_clock_highres: + def steady(): + if steady.use_clock_highres: try: time.clock_gettime(time.CLOCK_HIGHRES) except OSError: - monotonic.use_clock_highres = False - if monotonic.use_gethrtime: + steady.use_clock_highres = False + if steady.use_gethrtime: try: return time.gethrtime() except OSError: - monotonic.use_gethrtime = False + steady.use_gethrtime = False return time.time() - monotonic.use_clock_highres = (hasattr(time, 'clock_gettime') + steady.use_clock_highres = (hasattr(time, 'clock_gettime') and hasattr(time, 'CLOCK_HIGHRES')) - monotonic.use_gethrtime = True + steady.use_gethrtime = True elif hasattr(time, "clock_gettime"): - def monotonic(): - while monotonic.clocks: + def steady(): + while steady.clocks: try: - clk_id = monotonic.clocks[0] + clk_id = steady.clocks[0] return time.clock_gettime(clk_id) except OSError: - del monotonic.clocks[0] + del steady.clocks[0] return time.time() - monotonic.clocks = [] + steady.clocks = [] if hasattr(time, 'CLOCK_HIGHRES'): - monotonic.clocks.append(time.CLOCK_HIGHRES) - monotonic.clocks.append(time.CLOCK_MONOTONIC) + steady.clocks.append(time.CLOCK_HIGHRES) + steady.clocks.append(time.CLOCK_MONOTONIC) else: - def monotonic(): + def steady(): return time.time() On Windows, QueryPerformanceCounter() is not used even though it has a @@ -160,10 +158,10 @@ many issues. .. note:: - time.monotonic() detects GetTickCount() integer overflow (32 bits, + time.steady() detects GetTickCount() integer overflow (32 bits, roll-over after 49.7 days): it increases a delta by 2\ :sup:`32` each time than an overflow is detected. The delta is stored in the - process-local state and so the value of time.monotonic() may be + process-local state and so the value of time.steady() may be different in two Python processes. @@ -185,15 +183,15 @@ Pseudo-code:: # hardware does not support a high-resolution performance # counter for example highres.use_performance_counter = False - if highres.use_monotonic: + if highres.use_steady: # Monotonic clock is preferred over system clock try: - return time.monotonic() + return time.steady() except OSError: - highres.use_monotonic = False + highres.use_steady = False return time.time() highres.use_performance_counter = (os.name == 'nt') - highres.use_monotonic = hasattr(time, 'monotonic') + highres.use_steady = hasattr(time, 'steady') time.get_clock_info(name) ------------------------- @@ -202,7 +200,7 @@ Get information on the specified clock. Supported clocks: * "clock": time.clock() * "highres": time.highres() - * "monotonic": time.monotonic() + * "steady": time.steady() * "time": time.time() Return a dictionary with the following keys: @@ -766,10 +764,11 @@ time.highres(): * time.timer(): "it would be too easy to confuse with (or misspell as) time.time()" -time.monotonic(): +time.steady(): -* time.steady(): no OS provides a clock advancing at a steady rate, so - "steady" should be avoided. +* time.monotonic(): QueryPerformanceCounter() is monotonic but it is not used + by time.steady() because it is not steady, and it is surprising to have to + check for time.get_clock_info('monotonic')['is_monotonic']. * time.try_monotonic(): it is a clear and obvious solution for the use-case of "I prefer the monotonic clock, if it is available, otherwise I'll take my chances with a best-effect clock."