[Python-checkins] peps: PEP 418: Add fallback=True argument to time.monotonic()
victor.stinner
python-checkins at python.org
Sat Mar 31 01:21:28 CEST 2012
http://hg.python.org/peps/rev/9e1dfb3d8c50
changeset: 4176:9e1dfb3d8c50
user: Victor Stinner <victor.stinner at gmail.com>
date: Sat Mar 31 00:50:05 2012 +0200
summary:
PEP 418: Add fallback=True argument to time.monotonic()
* time.monotonic() doesn't use QPC anymore
* Rewrite also time.monotonic() and time.highres() definitions.
files:
pep-0418.txt | 88 ++++++++++++++++++++++++---------------
1 files changed, 53 insertions(+), 35 deletions(-)
diff --git a/pep-0418.txt b/pep-0418.txt
--- a/pep-0418.txt
+++ b/pep-0418.txt
@@ -13,7 +13,7 @@
Abstract
========
-Add time.monotonic() and time.highres() functions to Python 3.3.
+Add time.monotonic(fallback=True) and time.highres() functions to Python 3.3.
Rationale
@@ -24,12 +24,19 @@
* Display the current time to a human (e.g. display a calendar or draw a wall
clock): use system clock. time.time() or datetime.datetime.now()
* Benchmark, profiling, timeout: time.highres()
- * Event scheduler: time.monotonic()
+ * Event scheduler: time.monotonic(), or time.monotonic(fallback=False)
Functions
=========
+ * time.time(): system clock, "wall clock"
+ * time.highres(): clock with the best accuracy
+ * time.monotonic(fallback=True): monotonic clock. If no monotonic clock is
+ available, falls back to system clock by default, or raises an OSError if
+ *fallback* is False. time.monotonic(fallback=True) cannot go backward.
+
+
time.time()
-----------
@@ -68,12 +75,12 @@
return _time.time()
-time.monotonic()
-----------------
+time.monotonic(fallback=True)
+-----------------------------
-Clock advancing at a monotonic rate relative to real time. It 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.
+Clock that cannot go backward, 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.
It is not available on all platforms and may raise an OSError. It is not
available on GNU/Hurd for example.
@@ -85,34 +92,21 @@
if os.name == 'nt':
# GetTickCount64() requires Windows Vista, Server 2008 or later
if hasattr(time, '_GetTickCount64'):
- _get_tick_count = _time.GetTickCount64
+ def monotonic(fallback=True):
+ return _time.GetTickCount64()
else:
- def _get_tick_count():
+ def monotonic(fallback=True):
ticks = _time.GetTickCount()
- if ticks < _get_tick_count.last:
+ if ticks < monotonic.last:
# Integer overflow detected
- _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
+ monotonic.delta += 2**32
+ monotonic.last = ticks
+ return ticks + monotonic.delta
+ monotonic.last = 0
+ monotonic.delta = 0
elif os.name == 'mac':
- def monotonic():
+ def monotonic(fallback=True):
if monotonic.factor is None:
factor = _time.mach_timebase_info()
monotonic.factor = timebase[0] / timebase[1]
@@ -120,31 +114,45 @@
monotonic.factor = None
elif os.name.startswith('sunos'):
- def monotonic():
+ def monotonic(fallback=True):
if monotonic.use_clock_highres:
try:
time.clock_gettime(time.CLOCK_HIGHRES)
except OSError:
monotonic.use_clock_highres = False
- return time.gethrtime()
+ if monotonic.use_gethrtime:
+ try:
+ return time.gethrtime()
+ except OSError:
+ if not fallback:
+ raise
+ monotonic.use_gethrtime = False
+ return time.time()
monotonic.use_clock_highres = (hasattr(time, 'clock_gettime')
and hasattr(time, 'CLOCK_HIGHRES'))
+ monotonic.use_gethrtime = True
elif hasattr(time, "clock_gettime"):
- def monotonic():
+ def monotonic(fallback=True):
while monotonic.clocks:
try:
clk_id = monotonic.clocks[0]
return time.clock_gettime(clk_id)
except OSError:
# CLOCK_MONOTONIC_RAW requires a Linux kernel >= 2.6.28
+ if len(monotonic.clocks) == 1 and not fallback:
+ raise
del monotonic.clocks[0]
- return time.clock_gettime(time.CLOCK_MONOTONIC)
+ return time.time()
monotonic.clocks = []
if hasattr(time, 'CLOCK_MONOTONIC_RAW'):
monotonic.clocks.append(time.CLOCK_MONOTONIC_RAW)
if hasattr(time, 'CLOCK_HIGHRES'):
monotonic.clocks.append(time.CLOCK_HIGHRES)
+ monotonic.clocks.append(time.CLOCK_MONOTONIC)
+
+On Windows, QueryPerformanceCounter() is not used even if it has a better
+resolution than GetTickCount(). It is not reliable and has too much issues.
.. note::
@@ -157,20 +165,29 @@
time.highres()
--------------
-High-resolution clock: use a monotonic clock if available, or fallback to the
-system time.
+Clock with the best available resolution.
It is available on all platforms and cannot fail.
Pseudo-code::
def highres():
+ 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
if highres.use_monotonic:
+ # Monotonic clock is preferred over system clock
try:
return time.monotonic()
except OSError:
highres.use_monotonic = False
return time.time()
+ highres.use_performance_counter = (os.name == 'nt')
highres.use_monotonic = hasattr(time, 'monotonic')
--
Repository URL: http://hg.python.org/peps
More information about the Python-checkins
mailing list