2012-03-26 19:12:03 -04:00
|
|
|
PEP: 418
|
2012-03-27 13:27:28 -04:00
|
|
|
Title: Add monotonic and high-resolution time functions
|
2012-03-26 19:12:03 -04:00
|
|
|
Version: $Revision$
|
|
|
|
Last-Modified: $Date$
|
|
|
|
Author: Victor Stinner <victor.stinner@gmail.com>
|
|
|
|
Status: Draft
|
|
|
|
Type: Standards Track
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
Created: 26-March-2012
|
|
|
|
Python-Version: 3.3
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
========
|
|
|
|
|
2012-03-30 18:50:05 -04:00
|
|
|
Add time.monotonic(fallback=True) and time.highres() functions to Python 3.3.
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
=========
|
|
|
|
|
|
|
|
Use cases:
|
|
|
|
|
2012-03-27 13:27:28 -04:00
|
|
|
* 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()
|
2012-03-28 09:02:58 -04:00
|
|
|
* Benchmark, profiling, timeout: time.highres()
|
2012-03-30 18:50:05 -04:00
|
|
|
* Event scheduler: time.monotonic(), or time.monotonic(fallback=False)
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
|
2012-03-26 19:30:38 -04:00
|
|
|
Functions
|
|
|
|
=========
|
|
|
|
|
2012-03-30 18:50:05 -04:00
|
|
|
* 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.
|
|
|
|
|
|
|
|
|
2012-03-27 13:27:28 -04:00
|
|
|
time.time()
|
2012-03-26 19:30:38 -04:00
|
|
|
-----------
|
|
|
|
|
2012-03-27 13:27:28 -04:00
|
|
|
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
|
2012-03-27 20:18:11 -04:00
|
|
|
forward. It is not monotonic.
|
2012-03-27 13:27:28 -04:00
|
|
|
|
2012-03-27 19:45:51 -04:00
|
|
|
It is available on all platforms and cannot fail.
|
2012-03-27 13:27:28 -04:00
|
|
|
|
2012-03-27 19:57:37 -04:00
|
|
|
Pseudo-code [#pseudo]_: ::
|
2012-03-27 13:34:04 -04:00
|
|
|
|
|
|
|
if os.name == "nt":
|
|
|
|
def time():
|
|
|
|
return _time.GetSystemTimeAsFileTime()
|
|
|
|
else:
|
|
|
|
def time():
|
2012-03-27 19:57:37 -04:00
|
|
|
if hasattr(time, "clock_gettime"):
|
|
|
|
try:
|
|
|
|
# resolution = 1 nanosecond
|
|
|
|
return time.clock_gettime(time.CLOCK_REALTIME)
|
|
|
|
except OSError:
|
|
|
|
# CLOCK_REALTIME is not supported (unlikely)
|
|
|
|
pass
|
2012-03-27 13:34:04 -04:00
|
|
|
if hasattr(_time, "gettimeofday"):
|
|
|
|
try:
|
|
|
|
# resolution = 1 microsecond
|
|
|
|
return _time.gettimeofday()
|
|
|
|
except OSError:
|
2012-03-27 19:57:37 -04:00
|
|
|
# gettimeofday() should not fail
|
2012-03-27 13:34:04 -04:00
|
|
|
pass
|
|
|
|
if hasattr(_time, "ftime"):
|
|
|
|
# resolution = 1 millisecond
|
|
|
|
return _time.ftime()
|
|
|
|
else:
|
|
|
|
# resolution = 1 second
|
|
|
|
return _time.time()
|
|
|
|
|
2012-03-27 13:27:28 -04:00
|
|
|
|
2012-03-30 18:50:05 -04:00
|
|
|
time.monotonic(fallback=True)
|
|
|
|
-----------------------------
|
2012-03-27 13:27:28 -04:00
|
|
|
|
2012-03-30 18:50:05 -04:00
|
|
|
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.
|
2012-03-27 20:18:11 -04:00
|
|
|
|
2012-03-28 18:57:15 -04:00
|
|
|
It is not available on all platforms and may raise an OSError. It is not
|
|
|
|
available on GNU/Hurd for example.
|
2012-03-27 13:27:28 -04:00
|
|
|
|
|
|
|
The monotonic clock may stop while the system is suspended.
|
|
|
|
|
2012-03-27 19:57:37 -04:00
|
|
|
Pseudo-code [#pseudo]_: ::
|
2012-03-27 13:27:28 -04:00
|
|
|
|
|
|
|
if os.name == 'nt':
|
2012-03-27 19:57:37 -04:00
|
|
|
# GetTickCount64() requires Windows Vista, Server 2008 or later
|
2012-03-27 13:27:28 -04:00
|
|
|
if hasattr(time, '_GetTickCount64'):
|
2012-03-30 18:50:05 -04:00
|
|
|
def monotonic(fallback=True):
|
|
|
|
return _time.GetTickCount64()
|
2012-03-27 13:27:28 -04:00
|
|
|
else:
|
2012-03-30 18:50:05 -04:00
|
|
|
def monotonic(fallback=True):
|
2012-03-27 13:27:28 -04:00
|
|
|
ticks = _time.GetTickCount()
|
2012-03-30 18:50:05 -04:00
|
|
|
if ticks < monotonic.last:
|
2012-03-27 13:27:28 -04:00
|
|
|
# Integer overflow detected
|
2012-03-30 18:50:05 -04:00
|
|
|
monotonic.delta += 2**32
|
|
|
|
monotonic.last = ticks
|
|
|
|
return ticks + monotonic.delta
|
|
|
|
monotonic.last = 0
|
|
|
|
monotonic.delta = 0
|
2012-03-27 19:45:51 -04:00
|
|
|
|
|
|
|
elif os.name == 'mac':
|
2012-03-30 18:50:05 -04:00
|
|
|
def monotonic(fallback=True):
|
2012-03-27 13:27:28 -04:00
|
|
|
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
|
2012-03-27 19:45:51 -04:00
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
elif os.name.startswith('sunos'):
|
2012-03-30 18:50:05 -04:00
|
|
|
def monotonic(fallback=True):
|
2012-03-28 09:02:58 -04:00
|
|
|
if monotonic.use_clock_highres:
|
|
|
|
try:
|
|
|
|
time.clock_gettime(time.CLOCK_HIGHRES)
|
|
|
|
except OSError:
|
|
|
|
monotonic.use_clock_highres = False
|
2012-03-30 18:50:05 -04:00
|
|
|
if monotonic.use_gethrtime:
|
|
|
|
try:
|
|
|
|
return time.gethrtime()
|
|
|
|
except OSError:
|
|
|
|
if not fallback:
|
|
|
|
raise
|
|
|
|
monotonic.use_gethrtime = False
|
|
|
|
return time.time()
|
2012-03-28 09:02:58 -04:00
|
|
|
monotonic.use_clock_highres = (hasattr(time, 'clock_gettime')
|
|
|
|
and hasattr(time, 'CLOCK_HIGHRES'))
|
2012-03-30 18:50:05 -04:00
|
|
|
monotonic.use_gethrtime = True
|
2012-03-28 09:02:58 -04:00
|
|
|
|
2012-03-27 19:57:37 -04:00
|
|
|
elif hasattr(time, "clock_gettime"):
|
2012-03-30 18:50:05 -04:00
|
|
|
def monotonic(fallback=True):
|
2012-03-28 09:02:58 -04:00
|
|
|
while monotonic.clocks:
|
2012-03-27 13:27:28 -04:00
|
|
|
try:
|
2012-03-28 09:02:58 -04:00
|
|
|
clk_id = monotonic.clocks[0]
|
|
|
|
return time.clock_gettime(clk_id)
|
2012-03-27 13:27:28 -04:00
|
|
|
except OSError:
|
2012-03-27 19:45:51 -04:00
|
|
|
# CLOCK_MONOTONIC_RAW requires a Linux kernel >= 2.6.28
|
2012-03-30 18:50:05 -04:00
|
|
|
if len(monotonic.clocks) == 1 and not fallback:
|
|
|
|
raise
|
2012-03-28 09:02:58 -04:00
|
|
|
del monotonic.clocks[0]
|
2012-03-30 18:50:05 -04:00
|
|
|
return time.time()
|
2012-03-28 09:02:58 -04:00
|
|
|
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)
|
2012-03-30 18:50:05 -04:00
|
|
|
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.
|
2012-03-28 09:02:58 -04:00
|
|
|
|
2012-03-28 18:57:15 -04:00
|
|
|
.. note::
|
|
|
|
|
|
|
|
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
|
|
|
|
time.monotonic() value may be different in two Python processes.
|
|
|
|
|
2012-03-27 13:27:28 -04:00
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
time.highres()
|
|
|
|
--------------
|
2012-03-27 13:27:28 -04:00
|
|
|
|
2012-03-30 18:50:05 -04:00
|
|
|
Clock with the best available resolution.
|
2012-03-27 13:27:28 -04:00
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
It is available on all platforms and cannot fail.
|
2012-03-26 19:30:38 -04:00
|
|
|
|
2012-03-27 20:59:01 -04:00
|
|
|
Pseudo-code::
|
2012-03-27 13:27:28 -04:00
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
def highres():
|
2012-03-30 19:39:46 -04:00
|
|
|
if highres.use_performance_counter:
|
2012-03-30 18:50:05 -04:00
|
|
|
try:
|
|
|
|
return _time.QueryPerformanceCounter()
|
|
|
|
except OSError:
|
|
|
|
# QueryPerformanceFrequency() may fail, if the installed
|
|
|
|
# hardware does not support a high-resolution performance
|
|
|
|
# counter for example
|
2012-03-30 19:39:46 -04:00
|
|
|
highres.use_performance_counter = False
|
2012-03-28 09:02:58 -04:00
|
|
|
if highres.use_monotonic:
|
2012-03-30 18:50:05 -04:00
|
|
|
# Monotonic clock is preferred over system clock
|
2012-03-27 13:27:28 -04:00
|
|
|
try:
|
|
|
|
return time.monotonic()
|
2012-03-27 20:18:11 -04:00
|
|
|
except OSError:
|
2012-03-28 09:02:58 -04:00
|
|
|
highres.use_monotonic = False
|
2012-03-27 13:27:28 -04:00
|
|
|
return time.time()
|
2012-03-30 18:50:05 -04:00
|
|
|
highres.use_performance_counter = (os.name == 'nt')
|
2012-03-28 09:02:58 -04:00
|
|
|
highres.use_monotonic = hasattr(time, 'monotonic')
|
2012-03-26 19:30:38 -04:00
|
|
|
|
|
|
|
|
2012-03-26 19:12:03 -04:00
|
|
|
Clocks
|
|
|
|
======
|
|
|
|
|
2012-03-30 19:39:46 -04:00
|
|
|
Monotonic clocks
|
|
|
|
----------------
|
2012-03-29 21:41:03 -04:00
|
|
|
|
2012-03-30 07:53:40 -04:00
|
|
|
========================= =============== =============== ================ ====================
|
|
|
|
Name Resolution Accuracy Adjusted by NTP? Action on suspend
|
|
|
|
========================= =============== =============== ================ ====================
|
2012-03-30 17:16:06 -04:00
|
|
|
CLOCK_MONOTONIC_RAW 1 ns (*) No Stopped
|
|
|
|
gethrtime 1 ns (*) No Not stopped
|
|
|
|
CLOCK_HIGHRES 1 ns (*) No ?
|
|
|
|
CLOCK_MONOTONIC 1 ns (*) Yes on Linux Stopped on Linux
|
2012-03-30 07:53:40 -04:00
|
|
|
mach_absolute_time() 1 ns ? No ?
|
|
|
|
QueryPerformanceCounter() \- 0.3 ns - 5 ns No Accuracy issue
|
|
|
|
GetTickCount[64]() 1 ms 1 ms - 15 ms No Include suspend time
|
|
|
|
timeGetTime() 1 ms 1 ms - 15 ms No ?
|
|
|
|
========================= =============== =============== ================ ====================
|
|
|
|
|
2012-03-30 19:39:46 -04:00
|
|
|
(*) The accurary of monotonic clocks depends on the operating system and the
|
|
|
|
hardware clock.
|
2012-03-30 17:16:06 -04:00
|
|
|
|
2012-03-30 07:53:40 -04:00
|
|
|
The resolution is the smallest difference between two timestamps supported by
|
|
|
|
the format used by the clock. For example, clock_gettime() uses a timespec
|
|
|
|
structure which has two integer fileds, tv_sec and tv_nsec, so the resolution
|
|
|
|
is 1 nanosecond.
|
|
|
|
|
|
|
|
The accuracy is the effective smallest difference of two timestamps of the
|
|
|
|
clock. It does not reflect the stability the clock rate. For example,
|
|
|
|
QueryPerformanceCounter() has a good accuracy but is known to not have a steady
|
|
|
|
rate.
|
|
|
|
|
2012-03-29 21:41:03 -04:00
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
mach_absolute_time
|
|
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
|
2012-03-27 20:59:01 -04:00
|
|
|
Mac OS X provides a monotonic clock: mach_absolute_time(). It is based on
|
|
|
|
absolute elapsed time delta since system boot. It is not adjusted and cannot be
|
|
|
|
set.
|
2012-03-27 20:18:11 -04:00
|
|
|
|
2012-03-27 20:59:01 -04:00
|
|
|
mach_timebase_info() gives a fraction to convert the clock value to a number of
|
|
|
|
nanoseconds. According to the documentation (`Technical Q&A QA1398
|
|
|
|
<https://developer.apple.com/library/mac/#qa/qa1398/>`_), mach_timebase_info()
|
|
|
|
is always equals to one and does never fail, even if the function may fail
|
|
|
|
according to its prototype.
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-29 22:21:11 -04:00
|
|
|
mach_absolute_time() stops during a sleep on PowerPC CPU, but not on Intel CPU:
|
|
|
|
`Different behaviour of mach_absolute_time() on i386 / ppc
|
|
|
|
<http://lists.apple.com/archives/PerfOptimization-dev/2006/Jul/msg00024.html>`_.
|
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
mach_absolute_time() has a resolution of 1 nanosecond.
|
|
|
|
|
|
|
|
CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
|
|
CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW represents monotonic time since some
|
|
|
|
unspecified starting point. They cannot be set.
|
|
|
|
|
2012-03-28 20:10:32 -04:00
|
|
|
Documentation: refer to the manual page of your operating system. Examples:
|
|
|
|
|
|
|
|
* `FreeBSD clock_gettime() manual page
|
|
|
|
<http://www.freebsd.org/cgi/man.cgi?query=clock_gettime>`_
|
|
|
|
* `Linux clock_gettime() manual page
|
|
|
|
<http://linux.die.net/man/3/clock_gettime>`_
|
|
|
|
|
2012-03-28 18:57:15 -04:00
|
|
|
CLOCK_MONOTONIC is available at least on the following operating systems:
|
|
|
|
|
|
|
|
* DragonFly BSD, FreeBSD >= 5.0, OpenBSD, NetBSD
|
|
|
|
* Linux
|
|
|
|
* Solaris
|
|
|
|
|
|
|
|
The following operating systems don't support CLOCK_MONOTONIC:
|
|
|
|
|
|
|
|
|
|
|
|
* GNU/Hurd (see `open issues/ clock_gettime <http://www.gnu.org/software/hurd/open_issues/clock_gettime.html>`_)
|
|
|
|
* Mac OS X
|
|
|
|
* Windows
|
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
CLOCK_MONOTONIC_RAW is specific to Linux. It is similar to CLOCK_MONOTONIC, but
|
|
|
|
provides access to a raw hardware-based time that is not subject to NTP
|
|
|
|
adjustments. CLOCK_MONOTONIC_RAW requires Linux 2.6.28 or later.
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
On Linux, NTP may adjust CLOCK_MONOTONIC rate, but not jump backward. If
|
|
|
|
available, CLOCK_MONOTONIC_RAW should be used instead of CLOCK_MONOTONIC to
|
2012-03-27 20:18:11 -04:00
|
|
|
avoid the NTP adjustement.
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
CLOCK_MONOTONIC stops while the machine is suspended.
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
clock_gettime() fails if the system does not support the specified clock,
|
|
|
|
whereas the standard C library supports it. For example, CLOCK_MONOTONIC_RAW
|
|
|
|
requires a kernel version 2.6.28 or later.
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
clock_getres() gives the clock resolution. It is 1 nanosecond on Linux.
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-27 19:57:37 -04:00
|
|
|
.. note::
|
2012-03-27 20:59:01 -04:00
|
|
|
clock_gettime() requires to link the program to the rt (real-time) library.
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
Windows: QueryPerformanceCounter
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
2012-03-27 20:18:11 -04:00
|
|
|
|
|
|
|
High-resolution performance counter. It is monotonic.
|
2012-03-28 20:10:32 -04:00
|
|
|
QueryPerformanceFrequency() gives its frequency.
|
|
|
|
|
2012-03-29 21:41:03 -04:00
|
|
|
It has much higher resolution, but has lower long term accuracy than
|
|
|
|
GetTickCount() and timeGetTime() clocks. For example, it will drift compared to
|
|
|
|
the low precision clocks.
|
|
|
|
|
2012-03-28 20:10:32 -04:00
|
|
|
Documentation:
|
|
|
|
|
|
|
|
* `MSDN: QueryPerformanceCounter() documentation
|
|
|
|
<http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904%28v=vs.85%29.aspx>`_
|
|
|
|
* `MSDN: QueryPerformanceFrequency() documentation
|
|
|
|
<http://msdn.microsoft.com/en-us/library/windows/desktop/ms644905%28v=vs.85%29.aspx>`_
|
|
|
|
|
|
|
|
Hardware clocks used by QueryPerformanceCounter:
|
2012-03-27 20:18:11 -04:00
|
|
|
|
2012-03-28 19:57:15 -04:00
|
|
|
* Windows XP: RDTSC instruction of Intel processors, the clock frequency is
|
2012-03-28 20:10:32 -04:00
|
|
|
the frequency of the processor (between 200 MHz and 3 GHz, usually greater
|
|
|
|
than 1 GHz nowadays)
|
2012-03-29 21:41:03 -04:00
|
|
|
* Windows 2000: ACPI power management timer, frequency = 3,549,545 Hz. It can
|
|
|
|
be forced through the "/usepmtimer" flag in boot.ini
|
2012-03-28 19:57:15 -04:00
|
|
|
* Windows 95/98: 8245 PIT chipset, frequency = 1,193,181 Hz
|
2012-03-27 20:18:11 -04:00
|
|
|
|
|
|
|
QueryPerformanceFrequency() should only be called once: the frequency will not
|
|
|
|
change while the system is running. It fails if the installed hardware does not
|
|
|
|
support a high-resolution performance counter.
|
|
|
|
|
2012-03-29 21:41:03 -04:00
|
|
|
QueryPerformanceCounter() cannot be adjusted: `SetSystemTimeAdjustment()
|
|
|
|
<http://msdn.microsoft.com/en-us/library/windows/desktop/ms724943(v=vs.85).aspx>`_
|
|
|
|
does only adjust the system time.
|
|
|
|
|
2012-03-28 19:57:15 -04:00
|
|
|
Bugs:
|
|
|
|
|
|
|
|
* The performance counter value may unexpectedly leap forward because of a
|
|
|
|
hardware bug, see the `KB274323`_.
|
|
|
|
* On VirtualBox, QueryPerformanceCounter() does not increment the high part
|
|
|
|
every time the low part overflows, see `Monotonic timers
|
|
|
|
<http://code-factor.blogspot.fr/2009/11/monotonic-timers.html>`_ (2009).
|
|
|
|
* VirtualBox had a bug in its HPET virtualized device:
|
|
|
|
QueryPerformanceCounter() did jump forward by approx. 42 seconds (`issue
|
|
|
|
#8707 <https://www.virtualbox.org/ticket/8707>`_).
|
|
|
|
* Windows XP had a bug (see `KB896256`_): on a multiprocessor computer,
|
|
|
|
QueryPerformanceCounter() returned a different value for each processor.
|
2012-03-29 21:41:03 -04:00
|
|
|
The bug was fixed in Windows XP SP2.
|
2012-03-28 19:57:15 -04:00
|
|
|
|
2012-03-28 19:11:16 -04:00
|
|
|
.. _KB896256: http://support.microsoft.com/?id=896256
|
|
|
|
.. _KB274323: http://support.microsoft.com/?id=274323
|
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
Windows: GetTickCount(), GetTickCount64()
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
2012-03-27 20:18:11 -04:00
|
|
|
|
2012-03-29 21:41:03 -04:00
|
|
|
GetTickCount() and GetTickCount64() are monotonic, cannot fail and are not
|
|
|
|
adjusted by SetSystemTimeAdjustment(). MSDN documentation:
|
|
|
|
`GetTickCount() <http://msdn.microsoft.com/en-us/library/windows/desktop/ms724408(v=vs.85).aspx>`_,
|
|
|
|
`GetTickCount64() <http://msdn.microsoft.com/en-us/library/windows/desktop/ms724411(v=vs.85).aspx>`_.
|
2012-03-27 20:18:11 -04:00
|
|
|
|
2012-03-29 22:21:11 -04:00
|
|
|
The elapsed time retrieved by GetTickCount or GetTickCount64 includes time the
|
|
|
|
system spends in sleep or hibernation.
|
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
GetTickCount64() was added to Windows Vista and Windows Server 2008.
|
|
|
|
|
2012-03-28 18:57:15 -04:00
|
|
|
The clock resolution is 1 millisecond. Its accuracy is usually around 15 ms. It
|
|
|
|
is possible to improve the accuracy using the `undocumented
|
|
|
|
NtSetTimerResolution() function
|
|
|
|
<http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Time/NtSetTimerResolution.html>`_.
|
|
|
|
There are applications using this undocumented function, example:
|
|
|
|
`Timer Resolution <http://www.lucashale.com/timer-resolution/>`_.
|
|
|
|
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-29 21:41:03 -04:00
|
|
|
Windows: timeGetTime
|
|
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
|
|
The timeGetTime function retrieves the system time, in milliseconds. The system
|
|
|
|
time is the time elapsed since Windows was started. Read the `timeGetTime()
|
|
|
|
documentation
|
|
|
|
<http://msdn.microsoft.com/en-us/library/windows/desktop/dd757629(v=vs.85).aspx>`_.
|
|
|
|
|
|
|
|
The return type of timeGetTime() is a 32-bit unsigned integer. As
|
|
|
|
GetTickCount(), timeGetTime() rolls over after 2^32 milliseconds (49.7 days).
|
|
|
|
|
|
|
|
The default precision of the timeGetTime function can be five milliseconds or
|
|
|
|
more, depending on the machine.
|
|
|
|
|
|
|
|
timeBeginPeriod() can be used to increase the precision of timeGetTime() up to
|
2012-03-30 07:53:40 -04:00
|
|
|
1 millisecond, but it negatively affects power consumption.
|
2012-03-29 21:41:03 -04:00
|
|
|
|
|
|
|
.. note::
|
|
|
|
timeGetTime() and timeBeginPeriod() are part the Windows multimedia library
|
|
|
|
and so require to link the program with winmm or to load dynamically the
|
|
|
|
library.
|
|
|
|
|
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
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.
|
|
|
|
|
2012-03-29 22:21:11 -04:00
|
|
|
The linearity of gethrtime() is not preserved accross cpr suspend-resume cycle
|
|
|
|
(`Bug 4272663 <http://wesunsolve.net/bugid/id/4272663>`_).
|
|
|
|
|
2012-03-29 21:55:35 -04:00
|
|
|
Read the `gethrtime() manual page of Solaris 11
|
|
|
|
<http://docs.oracle.com/cd/E23824_01/html/821-1465/gethrtime-3c.html#scrolltoc>`_.
|
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
On Solaris, gethrtime() is the same as clock_gettime(CLOCK_MONOTONIC).
|
|
|
|
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-30 19:39:46 -04:00
|
|
|
System time clocks
|
|
|
|
------------------
|
2012-03-30 17:16:06 -04:00
|
|
|
|
|
|
|
========================= =============== ===============
|
|
|
|
Name Resolution Accuracy
|
|
|
|
========================= =============== ===============
|
|
|
|
CLOCK_REALTIME 1 ns (*)
|
|
|
|
GetSystemTimeAsFileTime 100 ns 1 ms - 15 ms
|
|
|
|
gettimeofday() 1 µs (*)
|
|
|
|
ftime() 1 ms (*)
|
|
|
|
time() 1 sec 1 sec
|
|
|
|
========================= =============== ===============
|
|
|
|
|
2012-03-30 19:39:46 -04:00
|
|
|
(*) The accurary of system clocks depends on the operating system and the
|
|
|
|
hardware clock. On Windows, the accuracy is in the range 1 ms - 15 ms.
|
2012-03-30 17:16:06 -04:00
|
|
|
|
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
Windows: GetSystemTimeAsFileTime
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
The system time can be read using GetSystemTimeAsFileTime(), ftime() and
|
|
|
|
time().
|
|
|
|
|
|
|
|
The system time resolution can be read using GetSystemTimeAdjustment(). The
|
2012-03-29 21:41:03 -04:00
|
|
|
accurary is usually between 1 millisecond and 15 milliseconds. Resolution:
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
* GetSystemTimeAsFileTime(): 100 nanoseconds
|
|
|
|
* ftime(): 1 millisecond
|
|
|
|
* time(): 1 second
|
|
|
|
|
|
|
|
The system time can be set using SetSystemTime().
|
|
|
|
|
|
|
|
System time on UNIX
|
|
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
gettimeofday(), ftime(), time() and clock_gettime(CLOCK_REALTIME) return the
|
2012-03-26 19:12:03 -04:00
|
|
|
system clock.
|
|
|
|
|
|
|
|
Resolution:
|
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
* clock_gettime(): clock_getres(CLOCK_REALTIME), 1 nanosecond on Linux
|
2012-03-26 19:12:03 -04:00
|
|
|
* gettimeofday(): 1 microsecond
|
|
|
|
* ftime(): 1 millisecond
|
|
|
|
* time(): 1 second
|
|
|
|
|
|
|
|
The system time can be set using settimeofday() or clock_settime(CLOCK_REALTIME).
|
|
|
|
|
|
|
|
|
|
|
|
Process and thread time
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
The process and thread time cannot be set. They are not monotonic: the clocks
|
|
|
|
stop while the process/thread is idle.
|
|
|
|
|
|
|
|
Process
|
|
|
|
^^^^^^^
|
|
|
|
|
|
|
|
* Windows: GetProcessTimes()
|
2012-03-27 20:18:11 -04:00
|
|
|
* clock_gettime(CLOCK_PROCESS_CPUTIME_ID): High-resolution per-process timer
|
|
|
|
from the CPU.
|
2012-03-26 19:12:03 -04:00
|
|
|
* clock():
|
|
|
|
|
|
|
|
* Windows: The elapsed wall-clock time since the start of the process
|
|
|
|
(elapsed time in seconds times CLOCKS_PER_SEC). It can fail.
|
|
|
|
* UNIX: returns an approximation of processor time used by the program.
|
|
|
|
|
|
|
|
* times()
|
|
|
|
* getrusage(): ru_utime and ru_stime fields
|
|
|
|
|
|
|
|
Resolution:
|
|
|
|
|
|
|
|
* clock() rate is CLOCKS_PER_SEC. It was called CLK_TCK in Microsoft C before
|
|
|
|
6.0. On Linux 3, clock() has a resolution of 1 microsecond
|
|
|
|
* The clock resolution can be read using clock_getres().
|
|
|
|
clock_getres(CLOCK_REALTIME) is 1 nanosecond on Linux
|
|
|
|
* GetProcessTimes(): call GetSystemTimeAdjustment()
|
|
|
|
|
|
|
|
Thread
|
|
|
|
^^^^^^
|
|
|
|
|
|
|
|
* Windows: GetThreadTimes()
|
|
|
|
* clock_gettime(CLOCK_THREAD_CPUTIME_ID): Thread-specific CPU-time clock.
|
|
|
|
|
|
|
|
Resolution:
|
|
|
|
|
|
|
|
* CLOCK_THREAD_CPUTIME_ID: call clock_getres(). 1 nanosecond on Linux.
|
|
|
|
* GetThreadTimes(): call GetSystemTimeAdjustment()
|
|
|
|
|
|
|
|
See also pthread_getcpuclockid().
|
|
|
|
|
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
Windows: QueryUnbiasedInterruptTime
|
2012-03-29 22:21:11 -04:00
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
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
|
|
|
|
transitions.
|
|
|
|
|
2012-03-29 22:21:11 -04:00
|
|
|
The elapsed time retrieved by the QueryUnbiasedInterruptTime function includes
|
|
|
|
only time that the system spends in the working state.
|
|
|
|
QueryUnbiasedInterruptTime() is not monotonic.
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
QueryUnbiasedInterruptTime() was introduced in Windows 7.
|
|
|
|
|
2012-03-30 07:53:40 -04:00
|
|
|
Linux timers
|
|
|
|
------------
|
|
|
|
|
|
|
|
There were 4 implementations of the time in the Linux kernel: UTIME (1996),
|
|
|
|
timer wheel (1997), HRT (2001) and hrtimers (2007). The later is the result of
|
|
|
|
the "high-res-timers" project started by George Anzinger in 2001, contributed
|
|
|
|
by Thomas Gleixner and Douglas Niehaus. hrtimers implementation was merged into
|
|
|
|
Linux 2.6.21 released in 2007.
|
|
|
|
|
|
|
|
hrtimers supports various clock sources. It sets a priority to each source to
|
|
|
|
decide which one will be used.
|
|
|
|
|
|
|
|
* TSC (Time Stamp Counter): Internal processor clock incremented at each
|
|
|
|
processor cycle. Its frequency is the processor frequency and so usually
|
|
|
|
higher than 1 GHz. Its priority is 300 by default, but falls to 0 if the
|
|
|
|
processor frequency changes and the counter becomes unstable.
|
|
|
|
* HPET: An HPET chip consists of a 64-bit up-counter (main counter) counting
|
|
|
|
at least at 10 MHz and a set of up to 256 comparators (at least 3). Each
|
|
|
|
HPET can have up to 32 timers.
|
|
|
|
* PIT (programmable interrupt timer): Intel 8253/8254 chipsets with a
|
|
|
|
configurable frequecency in range 18.2 Hz - 1.2 MHz. Linux uses the
|
|
|
|
frequency: 1,193,181.8 Hz. It is a 16-bit counter.
|
|
|
|
* PMTMR (power management timer): ACPI 24-bit timer with a frequency of 3.5
|
|
|
|
MHz (3,579,545 Hz). Its priority is 200 by default, but changes to 110 if
|
|
|
|
the chipset is broken and need a software workaround. HPET can cause around
|
|
|
|
3 seconds of drift per day.
|
|
|
|
* Cyclone: The Cyclone timer uses a 32-bit counter on IBM Extended
|
|
|
|
X-Architecture (EXA) chipsets which include computers that use the IBM
|
|
|
|
"Summit" series chipsets (ex: x440). This is available in IA32 and IA64
|
|
|
|
architectures.
|
|
|
|
|
|
|
|
High-resolution timers are not supported on all hardware architectures. They
|
|
|
|
are at least provided on x86/x86_64, ARM and PowerPC.
|
|
|
|
|
|
|
|
The list of available clock sources can be read in
|
|
|
|
/sys/devices/system/clocksource/clocksource0/available_clocksource. It is
|
|
|
|
possible to force a clocksource at runtime by writing its name into
|
|
|
|
/sys/devices/system/clocksource/clocksource0/current_clocksource.
|
|
|
|
/proc/timer_list contains the list of all hardware timers.
|
|
|
|
|
|
|
|
Read also the `time(7) manual page
|
|
|
|
<http://www.kernel.org/doc/man-pages/online/pages/man7/time.7.html>`_:
|
|
|
|
"overview of time and timers".
|
|
|
|
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-27 13:40:24 -04:00
|
|
|
Alternatives: API design
|
|
|
|
========================
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
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()
|
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
One function with a flag: time.monotonic(strict=False)
|
2012-03-28 09:02:58 -04:00
|
|
|
------------------------------------------------------
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-27 20:59:01 -04:00
|
|
|
* time.monotonic(strict=False) falls back to the system clock if no monotonic
|
|
|
|
clock is available or if the monotonic clock failed.
|
|
|
|
* time.monotonic(strict=True) raises OSError if monotonic clock fails and
|
2012-03-26 19:12:03 -04:00
|
|
|
NotImplementedError if the system does not provide a monotonic clock
|
|
|
|
|
|
|
|
"A keyword argument that gets passed as a constant in the caller is usually
|
|
|
|
poor API."
|
|
|
|
|
2012-03-26 19:30:38 -04:00
|
|
|
Raising NotImplementedError for a function is something uncommon in Python and
|
|
|
|
should be avoided.
|
|
|
|
|
2012-03-27 13:40:24 -04:00
|
|
|
|
2012-03-26 19:12:03 -04:00
|
|
|
One function, no flag
|
|
|
|
---------------------
|
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
time.monotonic() returns (time: float, is_monotonic: bool).
|
2012-03-26 19:12:03 -04:00
|
|
|
|
2012-03-27 20:18:11 -04:00
|
|
|
An alternative is to use a function attribute: time.monotonic.is_monotonic. The
|
|
|
|
attribute value would be None before the first call to time.monotonic().
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
|
2012-03-26 19:30:38 -04:00
|
|
|
Working around operating system bugs?
|
|
|
|
=====================================
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
Should Python ensure manually that a monotonic clock is truly monotonic by
|
|
|
|
computing the maximum with the clock value and the previous value?
|
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
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.
|
|
|
|
|
2012-03-26 19:12:03 -04:00
|
|
|
* Virtual machines provide less reliable clocks.
|
2012-03-28 19:57:15 -04:00
|
|
|
* QueryPerformanceCounter() has known bugs (only one is not fixed yet)
|
2012-03-28 19:11:16 -04:00
|
|
|
|
|
|
|
Python may only workaround a specific known operating system bug: `KB274323`_
|
|
|
|
contains a code example to workaround the bug (use GetTickCount() to detect
|
|
|
|
QueryPerformanceCounter() leap).
|
2012-03-26 19:12:03 -04:00
|
|
|
|
|
|
|
|
2012-03-27 19:57:37 -04:00
|
|
|
Footnotes
|
|
|
|
=========
|
|
|
|
|
2012-03-28 09:02:58 -04:00
|
|
|
.. [#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.
|
2012-03-27 19:57:37 -04:00
|
|
|
|
|
|
|
|
2012-03-26 19:12:03 -04:00
|
|
|
Links
|
|
|
|
=====
|
|
|
|
|
2012-03-28 18:57:15 -04:00
|
|
|
Related Python issues:
|
|
|
|
|
2012-03-26 20:19:00 -04:00
|
|
|
* `Issue #12822: NewGIL should use CLOCK_MONOTONIC if possible.
|
|
|
|
<http://bugs.python.org/issue12822>`_
|
|
|
|
* `Issue #14222: Use time.steady() to implement timeout
|
|
|
|
<http://bugs.python.org/issue14222>`_
|
|
|
|
* `Issue #14397: Use GetTickCount/GetTickCount64 instead of QueryPerformanceCounter for monotonic clock
|
|
|
|
<http://bugs.python.org/issue14397>`_
|
2012-03-28 09:02:58 -04:00
|
|
|
* `Issue #14428: Implementation of the PEP 418
|
|
|
|
<http://bugs.python.org/issue14428>`_
|
2012-03-28 18:57:15 -04:00
|
|
|
|
|
|
|
Librairies exposing monotonic clocks:
|
|
|
|
|
2012-03-29 19:53:38 -04:00
|
|
|
* `Java: System.nanoTime
|
|
|
|
<http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime()>`_
|
2012-03-26 20:19:00 -04:00
|
|
|
* `Qt library: QElapsedTimer
|
|
|
|
<http://qt-project.org/doc/qt-4.8/qelapsedtimer.html>`_
|
2012-03-28 18:57:15 -04:00
|
|
|
* `glib library: g_get_monotonic_time ()
|
2012-03-29 21:41:03 -04:00
|
|
|
<http://developer.gnome.org/glib/2.30/glib-Date-and-Time-Functions.html#g-get-monotonic-time>`_
|
2012-03-28 18:57:15 -04:00
|
|
|
uses GetTickCount64()/GetTickCount() on Windows,
|
|
|
|
clock_gettime(CLOCK_MONOTONIC) on UNIX or falls back to the system clock
|
2012-03-28 19:29:10 -04:00
|
|
|
* `python-monotonic-time
|
|
|
|
<http://code.google.com/p/python-monotonic-time/>`_
|
|
|
|
(`github <https://github.com/gavinbeatty/python-monotonic-time>`_)
|
2012-03-28 09:02:58 -04:00
|
|
|
* `monotonic_clock
|
2012-03-28 19:29:10 -04:00
|
|
|
<https://github.com/ThomasHabets/monotonic_clock>`_
|
2012-03-28 18:57:15 -04:00
|
|
|
* `Perl: Time::HiRes
|
|
|
|
<http://perldoc.perl.org/Time/HiRes.html>`_ exposes
|
|
|
|
clock_gettime(CLOCK_MONOTONIC)
|
2012-03-29 19:53:38 -04:00
|
|
|
* `Ruby: AbsoluteTime.now
|
|
|
|
<https://github.com/bwbuchanan/absolute_time/>`_: use
|
|
|
|
clock_gettime(CLOCK_MONOTONIC), mach_absolute_time() or gettimeofday().
|
|
|
|
"AbsoluteTime.monotonic?" method indicates if AbsoluteTime.now is monotonic
|
|
|
|
or not.
|
2012-03-28 18:57:15 -04:00
|
|
|
|
2012-03-29 21:41:03 -04:00
|
|
|
Time:
|
2012-03-28 18:57:15 -04:00
|
|
|
|
2012-03-30 07:53:40 -04:00
|
|
|
* `hrtimers - subsystem for high-resolution kernel timers
|
|
|
|
<http://www.kernel.org/doc/Documentation/timers/hrtimers.txt>`_
|
2012-03-28 18:57:15 -04:00
|
|
|
* `C++ Timeout Specification
|
|
|
|
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3128.html>`_
|
2012-03-26 19:12:03 -04:00
|
|
|
* `Windows: Game Timing and Multicore Processors
|
|
|
|
<http://msdn.microsoft.com/en-us/library/ee417693.aspx>`_
|
2012-03-27 19:45:51 -04:00
|
|
|
* `Implement a Continuously Updating, High-Resolution Time Provider for Windows
|
|
|
|
<http://msdn.microsoft.com/en-us/magazine/cc163996.aspx>`_
|
2012-03-29 21:41:03 -04:00
|
|
|
* `clockspeed <http://cr.yp.to/clockspeed.html>`_ uses a hardware tick counter
|
|
|
|
to compensate for a persistently fast or slow system clock
|
|
|
|
* `Retrieving system time
|
|
|
|
<http://en.wikipedia.org/wiki/System_time#Retrieving_system_time>`_
|
|
|
|
lists hardware clocks and time functions with their resolution
|
|
|
|
and epoch or range
|
|
|
|
* On Windows, the JavaScript runtime of Firefox interpolates
|
|
|
|
GetSystemTimeAsFileTime() with QueryPerformanceCounter() to get
|
|
|
|
an higher resolution. See the `Bug 363258 - bad millisecond resolution for
|
|
|
|
(new Date).getTime() / Date.now() on Windows
|
|
|
|
<https://bugzilla.mozilla.org/show_bug.cgi?id=363258>`_.
|
|
|
|
* `When microseconds matter
|
|
|
|
<http://www.ibm.com/developerworks/library/i-seconds/>`_: How the IBM High
|
|
|
|
Resolution Time Stamp Facility accurately measures itty bits of time
|
2012-03-26 19:12:03 -04:00
|
|
|
|