[Python-checkins] peps: Rewrite the PEP 418
victor.stinner
python-checkins at python.org
Wed Apr 4 02:58:04 CEST 2012
http://hg.python.org/peps/rev/5f1708dfd267
changeset: 4199:5f1708dfd267
user: Victor Stinner <victor.stinner at gmail.com>
date: Wed Apr 04 02:57:55 2012 +0200
summary:
Rewrite the PEP 418
* Rename time.steady() to time.monotonic(), again
* time.monotonic() does not fallback to the system clock anymore
* Drop time.perf_counter() function
files:
pep-0418.txt | 209 ++++++++++++++++----------------------
1 files changed, 86 insertions(+), 123 deletions(-)
diff --git a/pep-0418.txt b/pep-0418.txt
--- a/pep-0418.txt
+++ b/pep-0418.txt
@@ -1,5 +1,5 @@
PEP: 418
-Title: Add steady and high-resolution time functions
+Title: Add a monotonic time functions
Version: $Revision$
Last-Modified: $Date$
Author: Victor Stinner <victor.stinner at gmail.com>
@@ -13,8 +13,7 @@
Abstract
========
-Add time.steady(), time.perf_counter(), time.get_clock_info(name) functions to
-Python 3.3.
+Add time.monotonic() and time.get_clock_info(name) functions to Python 3.3.
Rationale
@@ -25,8 +24,9 @@
* Display the current time to a human (e.g. display a calendar or draw
a wall clock): use system clock, i.e. time.time() or
datetime.datetime.now().
-* Benchmark, profiling: time.perf_counter().
-* Event scheduler, timeout: time.steady().
+* Event scheduler, timeout: time.monotonic().
+* Benchmark, profiling: time.clock() on Windows, time.monotonic(),
+ or fallback to time.time()
Functions
@@ -35,8 +35,7 @@
To fulfill the use cases, the functions' properties are:
* time.time(): system clock, "wall clock".
-* time.perf_counter(): clock with the best accuracy.
-* time.steady(): steady clock, should be monotonic
+* time.monotonic(): monotonic clock
* time.get_clock_info(name): get information on the specified time function
@@ -78,129 +77,75 @@
return _time.time()
-time.steady()
--------------
+time.monotonic()
+----------------
-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('steady')['is_monotonic'] to check if the clock
-monotonic or not.
+Monotonic clock, cannot go backward. 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.
The elapsed time may or may not include time the system spends in
sleep or hibernation; this depends on the operating system.
+Availability: Windows, Mac OS X, Unix.
+
Pseudo-code [#pseudo]_::
if os.name == 'nt':
# GetTickCount64() requires Windows Vista, Server 2008 or later
if hasattr(time, '_GetTickCount64'):
- def steady():
+ def monotonic():
return _time.GetTickCount64() * 1e-3
else:
- def steady():
+ def monotonic():
ticks = _time.GetTickCount()
- if ticks < steady.last:
+ if ticks < monotonic.last:
# Integer overflow detected
- steady.delta += 2**32
- steady.last = ticks
- return (ticks + steady.delta) * 1e-3
- steady.last = 0
- steady.delta = 0
+ monotonic.delta += 2**32
+ monotonic.last = ticks
+ return (ticks + monotonic.delta) * 1e-3
+ monotonic.last = 0
+ monotonic.delta = 0
elif os.name == 'mac':
- def steady():
- if steady.factor is None:
+ def monotonic():
+ if monotonic.factor is None:
factor = _time.mach_timebase_info()
- steady.factor = timebase[0] / timebase[1]
- return _time.mach_absolute_time() * steady.factor
- steady.factor = None
+ monotonic.factor = timebase[0] / timebase[1]
+ return _time.mach_absolute_time() * monotonic.factor
+ monotonic.factor = None
- elif os.name.startswith('sunos'):
- def steady():
- if steady.use_clock_highres:
+ elif hasattr(time, "clock_gettime"):
+ def monotonic():
+ if monotonic.use_clock_highres:
try:
time.clock_gettime(time.CLOCK_HIGHRES)
except OSError:
- steady.use_clock_highres = False
- if steady.use_gethrtime:
- try:
- return time.gethrtime()
- except OSError:
- steady.use_gethrtime = False
- return time.time()
- steady.use_clock_highres = (hasattr(time, 'clock_gettime')
+ monotonic.use_clock_highres = False
+ return time.clock_gettime(time.CLOCK_MONOTONIC)
+ monotonic.use_clock_highres = (hasattr(time, 'clock_gettime')
and hasattr(time, 'CLOCK_HIGHRES'))
- steady.use_gethrtime = True
- elif hasattr(time, "clock_gettime"):
- def steady():
- while steady.clocks:
- try:
- clk_id = steady.clocks[0]
- return time.clock_gettime(clk_id)
- except OSError:
- del steady.clocks[0]
- return time.time()
- steady.clocks = []
- if hasattr(time, 'CLOCK_HIGHRES'):
- steady.clocks.append(time.CLOCK_HIGHRES)
- steady.clocks.append(time.CLOCK_MONOTONIC)
- else:
- def steady():
- return time.time()
-
-On Windows, QueryPerformanceCounter() is not used even though it has a
-better resolution than GetTickCount(). It is not reliable and has too
-many issues.
+On Windows, QueryPerformanceCounter() is not used even though it has a better
+accuracy than GetTickCount(). It is not reliable and has too many issues.
.. note::
- 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.steady() may be
- different in two Python processes.
+ time.monotonic() 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 different in two Python processes
+ running for more than 49 days.
-time.perf_counter()
--------------------
-
-Clock with the best available resolution.
-
-It is available on all platforms and cannot fail.
-
-Pseudo-code::
-
- def perf_counter():
- if perf_counter.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
- perf_counter.use_performance_counter = False
- if perf_counter.use_steady:
- # Monotonic clock is preferred over system clock
- try:
- return time.steady()
- except OSError:
- perf_counter.use_steady = False
- return time.time()
- perf_counter.use_performance_counter = (os.name == 'nt')
- perf_counter.use_steady = hasattr(time, 'steady')
-
time.get_clock_info(name)
-------------------------
Get information on the specified clock. Supported clocks:
* "clock": time.clock()
- * "perf_counter": time.perf_counter()
- * "steady": time.steady()
+ * "monotonic": time.monotonic()
* "time": time.time()
Return a dictionary with the following keys:
@@ -264,8 +209,8 @@
32,768 Hz
-NTP adjusted
-============
+NTP adjustment
+==============
NTP has diffent methods to adjust a clock:
@@ -655,10 +600,6 @@
always return 1 nanosecond. For GetProcessTimes(), the accuracy is read using
GetSystemTimeAdjustment().
-Python source code includes a portable library to get the process time:
-`Tools/pybench/systimes.py
-<http://hg.python.org/cpython/file/tip/Tools/pybench/systimes.py>`_.
-
Functions
^^^^^^^^^
@@ -793,27 +734,17 @@
Alternatives: API design
========================
-Other names for new functions
------------------------------
+Other names for time.monotonic()
+--------------------------------
-time.perf_counter():
-
-* time.highres()
-* time.hires(): "hires" can be read as "to hire" as in "he hires a car
- to go on holiday", rather than a "HIgh-RESolution clock".
-* time.timer(): "it would be too easy to confuse with (or misspell as)
- time.time()"
-
-time.steady():
-
-* 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."
+* time.steady()
* time.wallclock(): it is not the system time aka the "wall clock", but
a monotonic clock with an unspecified starting point
+* time.seconds()
+* time.counter()
+
+The name "time.try_monotonic()" was also proposed when time.monotonic() was
+falling back to the system clock when no monotonic clock was available.
Only expose operating system clocks
@@ -824,14 +755,18 @@
related clock identifiers were already added to Python 3.3 for example.
-Don't fallback on system clock
-------------------------------
+Fallback to system clock
+------------------------
-time.monotonic() is always a monotonic clock and is only available if the
-operating system provides a monotonic clock.
+If no monotonic clock is available, time.monotonic() falls back to the system
+clock.
-time.perf_counter() is only available if the operating system provides a clock
-with a high resolution (e.g. at least a microsecond or better).
+Issues:
+
+ * It is hard to define correctly such function in the documentation: is it
+ monotonic? is it steady? is it adjusted?
+ * Some user want to decide what to do when no monotonic clock is available:
+ use another clock, display an error, or do something else
One function choosing the clock from a list of constrains
@@ -846,7 +781,8 @@
time.get_clock() returns None if the clock is found and so calls can be chained
using the or operator. Example::
- func = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time()
+ get_time = time.get_clock(time.MONOTONIC) or time.get_clock(time.STEADY) or time.time()
+ t = get_time()
Example of flags of system clocks:
@@ -854,7 +790,7 @@
* GetTickCount: MONOTONIC | STEADY
* CLOCK_MONOTONIC: MONOTONIC | STEADY (or only MONOTONIC on Linux)
* CLOCK_MONOTONIC_RAW: MONOTONIC | STEADY
- * gettimeofday(): (none)
+ * gettimeofday(): (no flag)
One function with a flag: time.monotonic(fallback=True)
@@ -908,6 +844,29 @@
see the same clock value
+Deferred API: time.perf_counter()
+=================================
+
+Python does not provide a portable "performance counter" clock for benchmarking
+or profiling. Each tool has to implement its own heuristic to decide which
+clock is the best depending on the OS and on which counters are available.
+
+A previous version of the PEP proposed a time.perf_counter() function using
+QueryPerformanceCounter() on Windows, time.monotonic(), or falls back to the
+system time. This function was not well defined and the idea is deferred.
+
+Proposed names for such function:
+
+ * time.hires()
+ * time.highres()
+ * time.perf_counter()
+ * time.timer()
+
+Python source code includes a portable library to get the process time:
+`Tools/pybench/systimes.py
+<http://hg.python.org/cpython/file/tip/Tools/pybench/systimes.py>`_.
+
+
Footnotes
=========
--
Repository URL: http://hg.python.org/peps
More information about the Python-checkins
mailing list