PEP 418: Rename time.hires() to time.highres(); add Solaris monotonic clocks
Mention also other time.highres() name propositions.
This commit is contained in:
parent
aaa1107673
commit
319f49544b
105
pep-0418.txt
105
pep-0418.txt
|
@ -13,7 +13,7 @@ Python-Version: 3.3
|
|||
Abstract
|
||||
========
|
||||
|
||||
Add time.monotonic() and time.hires() functions to Python 3.3.
|
||||
Add time.monotonic() and time.highres() functions to Python 3.3.
|
||||
|
||||
|
||||
Rationale
|
||||
|
@ -23,7 +23,7 @@ Use cases:
|
|||
|
||||
* 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.hires()
|
||||
* Benchmark, profiling, timeout: time.highres()
|
||||
* Event scheduler: time.monotonic()
|
||||
|
||||
|
||||
|
@ -118,19 +118,36 @@ Pseudo-code [#pseudo]_: ::
|
|||
return _time.mach_absolute_time() * monotonic.factor
|
||||
monotonic.factor = None
|
||||
|
||||
elif os.name.startswith('sunos'):
|
||||
def monotonic():
|
||||
if monotonic.use_clock_highres:
|
||||
try:
|
||||
time.clock_gettime(time.CLOCK_HIGHRES)
|
||||
except OSError:
|
||||
monotonic.use_clock_highres = False
|
||||
return time.gethrtime()
|
||||
monotonic.use_clock_highres = (hasattr(time, 'clock_gettime')
|
||||
and hasattr(time, 'CLOCK_HIGHRES'))
|
||||
|
||||
elif hasattr(time, "clock_gettime"):
|
||||
def monotonic():
|
||||
if monotonic.use_monotonic_raw:
|
||||
while monotonic.clocks:
|
||||
try:
|
||||
return time.clock_gettime(time.CLOCK_MONOTONIC_RAW)
|
||||
clk_id = monotonic.clocks[0]
|
||||
return time.clock_gettime(clk_id)
|
||||
except OSError:
|
||||
# CLOCK_MONOTONIC_RAW requires a Linux kernel >= 2.6.28
|
||||
monotonic.use_monotonic_raw = False
|
||||
del monotonic.clocks[0]
|
||||
return time.clock_gettime(time.CLOCK_MONOTONIC)
|
||||
monotonic.use_monotonic_raw = hasattr(time, "CLOCK_MONOTONIC_RAW")
|
||||
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)
|
||||
|
||||
time.hires()
|
||||
------------
|
||||
|
||||
time.highres()
|
||||
--------------
|
||||
|
||||
High-resolution clock: use a monotonic clock if available, or fallback to the
|
||||
system time.
|
||||
|
@ -139,14 +156,14 @@ It is available on all platforms and cannot fail.
|
|||
|
||||
Pseudo-code::
|
||||
|
||||
def hires():
|
||||
if hires.use_monotonic:
|
||||
def highres():
|
||||
if highres.use_monotonic:
|
||||
try:
|
||||
return time.monotonic()
|
||||
except OSError:
|
||||
hires.use_monotonic = False
|
||||
highres.use_monotonic = False
|
||||
return time.time()
|
||||
hires.use_monotonic = hasattr(time, 'monotonic')
|
||||
highres.use_monotonic = hasattr(time, 'monotonic')
|
||||
|
||||
|
||||
Clocks
|
||||
|
@ -195,8 +212,8 @@ clock_getres() gives the clock resolution. It is 1 nanosecond on Linux.
|
|||
.. note::
|
||||
clock_gettime() requires to link the program to the rt (real-time) library.
|
||||
|
||||
QueryPerformanceCounter
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Windows: QueryPerformanceCounter
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
High-resolution performance counter. It is monotonic.
|
||||
QueryPerformanceFrequency() gives its frequency.
|
||||
|
@ -212,8 +229,8 @@ change while the system is running. It fails if the installed hardware does not
|
|||
support a high-resolution performance counter.
|
||||
|
||||
|
||||
GetTickCount(), GetTickCount64()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Windows: GetTickCount(), GetTickCount64()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
GetTickCount() and GetTickCount64() are monotonic and cannot fail.
|
||||
|
||||
|
@ -221,6 +238,27 @@ GetTickCount64() was added to Windows Vista and Windows Server 2008.
|
|||
|
||||
The clock resolution is 1 millisecond.
|
||||
|
||||
Solaris: CLOCK_HIGHRES
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Solaris OS has an CLOCK_HIGHRES timer that attempts to use an optimal
|
||||
hardware source, and may give close to nanosecond resolution. CLOCK_HIGHRES is
|
||||
the nonadjustable, high-resolution clock. For timers created with a clockid_t
|
||||
value of CLOCK_HIGHRES, the system will attempt to use an optimal hardware
|
||||
source.
|
||||
|
||||
Solaris: gethrtime
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The gethrtime() function returns the current high-resolution real time. Time is
|
||||
expressed as nanoseconds since some arbitrary time in the past; it is not
|
||||
correlated in any way to the time of day, and thus is not subject to
|
||||
resetting or drifting by way of adjtime() or settimeofday(). The hires timer
|
||||
is ideally suited to performance measurement tasks, where cheap, accurate
|
||||
interval timing is required.
|
||||
|
||||
On Solaris, gethrtime() is the same as clock_gettime(CLOCK_MONOTONIC).
|
||||
|
||||
|
||||
System time
|
||||
-----------
|
||||
|
@ -299,8 +337,8 @@ Resolution:
|
|||
See also pthread_getcpuclockid().
|
||||
|
||||
|
||||
QueryUnbiasedInterruptTime
|
||||
--------------------------
|
||||
Windows: QueryUnbiasedInterruptTime
|
||||
-----------------------------------
|
||||
|
||||
Gets the current unbiased interrupt time from the biased interrupt time and the
|
||||
current sleep bias amount. This time is not affected by power management sleep
|
||||
|
@ -311,12 +349,25 @@ Is it monotonic?
|
|||
QueryUnbiasedInterruptTime() was introduced in Windows 7.
|
||||
|
||||
|
||||
|
||||
Alternatives: API design
|
||||
========================
|
||||
|
||||
time.highres() function name
|
||||
----------------------------
|
||||
|
||||
Other names were proposed:
|
||||
|
||||
* 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.steady(): no OS provides a clock advancing at a steady rate, so
|
||||
"steady" should be avoided.
|
||||
* 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.wallclock()
|
||||
|
||||
One function with a flag: time.monotonic(strict=False)
|
||||
----------------------------------------------------------
|
||||
------------------------------------------------------
|
||||
|
||||
* time.monotonic(strict=False) falls back to the system clock if no monotonic
|
||||
clock is available or if the monotonic clock failed.
|
||||
|
@ -345,6 +396,10 @@ Working around operating system bugs?
|
|||
Should Python ensure manually that a monotonic clock is truly monotonic by
|
||||
computing the maximum with the clock value and the previous value?
|
||||
|
||||
Since it's relatively straightforward to cache the last value returned using a
|
||||
static variable, it might be interesting to use this to make sure that the
|
||||
values returned are indeed monotonic.
|
||||
|
||||
* Virtual machines provide less reliable clocks.
|
||||
* QueryPerformanceCounter() had a bug in 2006 on multiprocessor computers
|
||||
|
||||
|
@ -352,8 +407,8 @@ computing the maximum with the clock value and the previous value?
|
|||
Footnotes
|
||||
=========
|
||||
|
||||
.. [#pseudo] _time is an hypothetical module used for the example. In practice,
|
||||
functions will be implemented in C and so don't need a module.
|
||||
.. [#pseudo] "_time" is an hypothetical module only used for the example.
|
||||
The time module is implemented in C and so there is no need for such module.
|
||||
|
||||
|
||||
Links
|
||||
|
@ -365,15 +420,21 @@ Links
|
|||
<http://bugs.python.org/issue14222>`_
|
||||
* `Issue #14397: Use GetTickCount/GetTickCount64 instead of QueryPerformanceCounter for monotonic clock
|
||||
<http://bugs.python.org/issue14397>`_
|
||||
* `Issue #14428: Implementation of the PEP 418
|
||||
<http://bugs.python.org/issue14428>`_
|
||||
* `python-monotonic-time
|
||||
<http://code.google.com/p/python-monotonic-time/>`_
|
||||
(`github <https://github.com/gavinbeatty/python-monotonic-time>`_)
|
||||
* `Qt library: QElapsedTimer
|
||||
<http://qt-project.org/doc/qt-4.8/qelapsedtimer.html>`_
|
||||
* `monotonic_clock
|
||||
<https://github.com/ThomasHabets/monotonic_clock>`_
|
||||
* `Windows: Game Timing and Multicore Processors
|
||||
<http://msdn.microsoft.com/en-us/library/ee417693.aspx>`_
|
||||
* `Implement a Continuously Updating, High-Resolution Time Provider for Windows
|
||||
<http://msdn.microsoft.com/en-us/magazine/cc163996.aspx>`_
|
||||
* `Perl: Time::HiRes
|
||||
<http://perldoc.perl.org/Time/HiRes.html>`_
|
||||
* `C++ Timeout Specification
|
||||
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3128.html>`_
|
||||
|
||||
|
|
Loading…
Reference in New Issue