-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add time.monotonic() method #54487
Comments
If measuring time across blocking calls, such as thread synchronization, one currently must time.time(). This is because time.clock() measures cpu seconds on unix. On windows, however, time.clock() would be more appropriate because it measures wall-clock time. To avoid having to put platform clauses everywhere, this patch adds time.wallclock(). |
+1 |
Why does this need to be in stdlib? AFAICT, the proposed patch is just: if <appropriate test>:
wallclock = time.clock
else:
wallclock = time.time which is easy enough to stick in your measuring code or a project's utilities module. If others really want to see this in stdlib, I would prefer to place it in a more specialized module such as profile. |
Well, the problem is that the "appropriate test" is not easy to guess a priori, so it would be useful for the stdlib to provide the right tool for the job. |
On Mon, Nov 1, 2010 at 1:43 PM, Antoine Pitrou <report@bugs.python.org> wrote:
This sounds like an argument against this feature, not for it. If it
Having time.time and time.clock is already confusing enough. Having |
The point of a standard library is to bring together competence and
The problem is time.clock(), since it does two wildly different things |
On Mon, Nov 1, 2010 at 2:09 PM, Antoine Pitrou <report@bugs.python.org> wrote:
It looks like I misunderstood what you said. I thought "a priory" |
On Mon, Nov 1, 2010 at 2:09 PM, Antoine Pitrou <report@bugs.python.org> wrote:
+1, but doing something like that should be discussed on python-ideas |
Certainly. The main point, as Antoine points out, is that time.clock() means two seriously different things on the two main platforms, and time.clock() is potentially inadequate on one of them. I put in the patch since it was quick to do, but I'll provoke a discussion on python-ideas for now. |
2010/11/1 Kristján Valur Jónsson <report@bugs.python.org>:
I am looking forward to it. You may find reviewing the following |
I would also be nice to have a "monotonic" clock in Python. See monotonic.py for an example. But I don't know if it solves the same problem than time.wallclock() or not. I need a monotonic clock for a server on which NTP is sometimes called to resynchronize the system clock (and the NTP server may be change by the user). |
Well, that is sort of what I'm trying to achieve. Note that you probably want to use QueryPerformaceCounter on windows (or simply time.clock()) or at least GetTickCount64 which doesn't wrap around after 50 days :). Also, I'm trying to get the highest resolution possible... |
I agree with Victor: Python should provide a function to supply monotonic time, which is what's really wanted for measuring time deltas. Far too many applications incorrectly use the system clock for this, and Python makes this worse by not providing any standard library function to allow people to do this correctly. In Windows, it should probably use GetTickCount64 if available, otherwise GetTickCount with logic to handle wrapping. I think QueryPerformanceCounter is problematic as a general-purpose timer: depending on the hardware and Windows version, it can be offset differently across CPUs, and may not be reliable on some processors. It may be fixed in Vista or Win7, I'm not sure; if so it's much higher resolution than GTC. |
This is sorely needed. IMO the current behaviour of time.clock works for Windows, and clock_gettime(CLOCK_MONOTONIC) on POSIX or clock_gettime(CLOCK_MONOTONIC_RAW) on Linux>=2.6.28. There are some related discussions on StackOverflow that may contain useful ideas also: |
I don't have a ton of experience with this, but by creating a synchronization point based on when the system clock changes, QueryPerformanceCounter can be pretty accurate and as you already stated, and higher resolution than most other solutions. http://msdn.microsoft.com/en-us/magazine/cc163996.aspx is where I got the idea and most of the implementation from. I'm essentially using the code from Figure 2 in a C extension right now to do something similar to threading.Timer in a performance testing tool. |
What's the status of this bug? This is a very useful feature, I've had to use and add bindings to monotonic times for numerous applications. Can it make it into 3.3? |
See also bpo-12822. |
I think that we should process in two steps:
Low level functions:
High level:
I propose time.monotonic() because I saw this name in different projects. Pseudo-code for the time module: monotonic = None
if hasattr(time, 'clock_gettime'):
if hasattr(time, 'CLOCK_MONOTONIC_RAW'):
def monotonic(): return time.clock_gettime(CLOCK_MONOTONIC_RAW)
else:
# i don't think that we should expose clock_gettime
# if CLOCK_MONOTONIC is not available (or the function is useless)
def monotonic(): return time.clock_gettime(CLOCK_MONOTONIC)
elif os.name == 'nt':
def monotonic(): return time.clock()
if monotonic is not None:
monotonic.__doc__ = 'monotonic time'
else:
del monotonic |
Note: it would be very pratical if time.monotonic() has always the same unit on all platforms. clock_gettime() uses seconds (and nanoseconds), time.clock() uses also seconds. |
The problem with QueryPerformanceCounter is that it drifts. It has high resolution, but can drift far out of sync with GetTickCount64. QPC will wrap, but only after a long time. its 64 bits, and with a frequency of 1GHz, that takes some 600 years. |
clock_gettime.patch: add time.clock_gettime() function and time.CLOCK_xxx constants. The patch requires to rerun "autoconf". For the documentation, I don't know the availability of this function. Is it available on Windows? CLOCK_REALTIME doc contains "Setting this clock requires appropriate privileges": this sentence might be removed if we don't expose clock_settime. The constants are not defined if the function is not available. timemodule.c and datetimemodule.c are no more linked to libm. I don't know why libm was used? Copy/paste failure? On Linux, clock_gettime() requires librt. I chose to check for librt in configure.in. To get this info in setup.py, I close to use the TIMEMODULE_LIBS define (in pyconfig.h). I don't know if there is something simpler. time.clock_gettime() returns a float. It would be nice to keep nanoseconds as an integer, but I chose a float to mimic other time functions. If we need nanosecond resolution, a new function can be added. The unit test is very simple, but less than time.clock() test :-) |
The issue bpo-13261 has been marked as a duplicate of this issue. Copy of msg146347: The result of call to clock () changes once per several seconds. On the other side, on Windows it provides very good resolution. Here is a doctest that fails on Linux:
"""
>>> from time import sleep
>>> prev = clock ()
>>> res = True
>>> for i in xrange(10):
... sleep(0.15)
... next = clock ()
... res = res and (next - prev) > 0.1
... prev = next
>>> print res
True
""" Currently on Linux I am using a workaround that is attached to the issue. The issue has also a script: |
CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID are optional according to POSIX, which only mandates CLOCK_REALTIME. You should mention it in the docs. You might also want to export clock_getres(): |
New changeset 35e4b7c4bafa by Victor Stinner in branch 'default': |
I closed maybe this issue too quickly. My commit doesn't solve the initial issue: Python doesn't provide a portable "wallclock" function. wallclock.patch should be updated to use:
Pseudo-code: wallclock = None
if hasattr(time, 'clock_gettime') and hasattr(time, 'CLOCK_MONOTONIC_RAW'):
# I understood that CLOCK_MONOTONIC_RAW is more reliable
# than CLOCK_MONOTONIC, because CLOCK_MONOTONIC may be adjusted
# by NTP. I don't know if it's correct.
def wallclock():
return time.clock_gettime(CLOCK_MONOTONIC_RAW) elif hasattr(time, 'clock_gettime') and hasattr(time, 'CLOCK_MONOTONIC'): elif os.name == 'nt': else: wallclock() doc should also explain that time.time() may be adjusted by NTP or manually by the administrator. -- By the way, it would be nice to expose the precision of time.clock(): it's 1/divisor or 1/CLOCKS_PER_SEC on Windows, 1/CLOCKS_PER_SEC on UNIX. |
wallclock-2.patch: implement wallclock() using the new clock_getime(CLOCK_MONOTONIC) function (or other, depending on the OS). I removed description on how the function is implemented from the doc. |
As discussed elsewhere, there should be a fallback when clock_gettime() fails for the given clock. |
Version 3 of the patch: check for clock_gettime() failure. Try CLOCK_MONOTONIC_RAW, or try CLOCK_MONOTONIC, or use time.time(). |
on linux the underlying functionality is implemented in librt; the extension doesn't check for this or links with -lrt. |
The changeset 35e4b7c4bafa changed configure.in to check clock_gettime(). It checks without and with librt:
wallclock-3.patch checks for HAVE_CLOCK_GETTIME, which does use librt in its test (see above). |
then something like this is missing? diff -r ca2a35140e6a Modules/Setup.dist
--- a/Modules/Setup.dist Mon Jan 09 06:17:39 2012 +0000
+++ b/Modules/Setup.dist Mon Jan 09 15:25:05 2012 +0100
@@ -166,7 +166,7 @@
#cmath cmathmodule.c _math.c # -lm # complex math library functions
#math mathmodule.c _math.c # -lm # math library functions, e.g. sin()
#_struct _struct.c # binary structure packing/unpacking
-#time timemodule.c # -lm # time operations and variables
+#time timemodule.c $(TIMEMODULE_LIB) # -lm # time operations and variables
#_weakref _weakref.c # basic weak reference support
#_testcapi _testcapimodule.c # Python C API test module
#_random _randommodule.c # Random number generator |
New changeset bb10cd354e49 by Victor Stinner in branch 'default': |
New changeset 1de276420470 by Victor Stinner in branch 'default': |
There are some issue on the Windows buildbots: ====================================================================== Traceback (most recent call last):
File "D:\cygwin\home\db3l\buildarea\3.x.bolen-windows\build\lib\test\test_time.py", line 340, in test_wallclock
self.assertAlmostEqual(t, 0.1, places=2)
AssertionError: 0.09138312271531701 != 0.1 within 2 places |
New changeset 83e8c3a6a81c by Antoine Pitrou in branch 'default': |
New changeset 8502a9236c2e by Victor Stinner in branch 'default': |
New changeset fb0f4fe8123e by Victor Stinner in branch 'default': |
New changeset c11946846474 by Victor Stinner in branch 'default': |
New changeset 27441e0d6a75 by Victor Stinner in branch 'default': |
This issue has been followed by the PEP-418 which added time.monotonic(), time.perf_counter() and time.process_time(). |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: