Rename time.steady(strict=True) to time.monotonic()?
Hi, time.steady(strict=True) looks to be confusing for most people, some of them don't understand the purpose of the flag and others don't like a flag changing the behaviour of the function. I propose to replace time.steady(strict=True) by time.monotonic(). That would avoid the need of an ugly NotImplementedError: if the OS has no monotonic clock, time.monotonic() will just not exist. So we will have: - time.time(): realtime, can be adjusted by the system administrator (manually) or automatically by NTP - time.clock(): monotonic clock on Windows, CPU time on UNIX - time.monotonic(): monotonic clock, its speed may or may not be adjusted by NTP but it only goes forward, may raise an OSError - time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward. time.steady() is something like: try: return time.monotonic() except (NotImplementError, OSError): return time.time() time.time(), time.clock(), time.steady() are always available, whereas time.monotonic() will not be available on some platforms. Victor
On Mar 23, 2012 6:25 PM, "Victor Stinner" <victor.stinner@gmail.com> wrote:
Hi,
time.steady(strict=True) looks to be confusing for most people, some of them don't understand the purpose of the flag and others don't like a flag changing the behaviour of the function.
I propose to replace time.steady(strict=True) by time.monotonic(). That would avoid the need of an ugly NotImplementedError: if the OS has no monotonic clock, time.monotonic() will just not exist.
So we will have:
- time.time(): realtime, can be adjusted by the system administrator (manually) or automatically by NTP - time.clock(): monotonic clock on Windows, CPU time on UNIX - time.monotonic(): monotonic clock, its speed may or may not be adjusted by NTP but it only goes forward, may raise an OSError - time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward.
time.steady() is something like:
try: return time.monotonic() except (NotImplementError, OSError): return time.time()
time.time(), time.clock(), time.steady() are always available, whereas time.monotonic() will not be available on some platforms.
Victor
This seems like it should have been a PEP, or maybe should become a PEP.
This seems like it should have been a PEP, or maybe should become a PEP.
I replaced time.wallclock() by time.steady(strict=False) and time.monotonic() by time.steady(strict=True). This change solved the naming issue of time.wallclock(), but it was a bad idea to merge monotonic() feature into time.steady(). It looks like everybody agrees, am I wrong? Victor
On Sat, Mar 24, 2012 at 00:36, Victor Stinner <victor.stinner@gmail.com> wrote:
This seems like it should have been a PEP, or maybe should become a PEP.
I replaced time.wallclock() by time.steady(strict=False) and time.monotonic() by time.steady(strict=True). This change solved the naming issue of time.wallclock(), but it was a bad idea to merge monotonic() feature into time.steady(). It looks like everybody agrees, am I wrong?
Yes. As mentioned time.steady(i_mean_it=True) or time.steady(no_not_really=True) doesn't make any sense. Merging the methods may very well make sense, but it should then return a best case and have no flags. I think, as it has been hard to reach an agreement on this that the proposal to only make "stupid" functions that expose the system API's are the correct thing to do at the moment.
- time.time(): realtime, can be adjusted by the system administrator (manually) or automatically by NTP
Sure.
- time.clock(): monotonic clock on Windows, CPU time on UNIX
This is for historical reasons, right, because this is what it is now? Would there be a problem in making time.clock() monotonic on Unix as well, if it exists?
- time.monotonic(): monotonic clock, its speed may or may not be adjusted by NTP but it only goes forward, may raise an OSError if the OS has no monotonic clock, time.monotonic() will just not exist.
Works for me,
- time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward.
So it's time.may_or_may_not_be_steady() I don't mind the function, but the name should not be steady(). It's implementation is also so trivial that those who want a monotonic if it exists, but a normal clock otherwise, can simply just do
try: return time.monotonic() except (NotImplementError, OSError): return time.time()
themselves. //Lennart
On 2012-03-23, at 7:28 PM, Brian Curtin wrote:
This seems like it should have been a PEP, or maybe should become a PEP.
Why? AFAIK Victor just proposes to add two new functions: monotonic() and steady(). time() and clock() do already exist and won't be changed. - Yury
On Fri, Mar 23, 2012 at 18:38, Yury Selivanov <yselivanov.ml@gmail.com> wrote:
On 2012-03-23, at 7:28 PM, Brian Curtin wrote:
This seems like it should have been a PEP, or maybe should become a PEP.
Why? AFAIK Victor just proposes to add two new functions: monotonic() and steady().
We just previously had "Drop time.monotonic() function, rename time.wallclock() to time.steady()" checked in a few weeks ago, and now we're renaming a variation on time.steady to time.monotonic? What's the next move? I'm not paying close attention here but there's a lot of movement going on. Figuring out the API before we get too deep is probably a good idea.
On Fri, 23 Mar 2012 22:38:19 -0500 Brian Curtin <brian@python.org> wrote:
On Fri, Mar 23, 2012 at 18:38, Yury Selivanov <yselivanov.ml@gmail.com> wrote:
On 2012-03-23, at 7:28 PM, Brian Curtin wrote:
This seems like it should have been a PEP, or maybe should become a PEP.
Why? AFAIK Victor just proposes to add two new functions: monotonic() and steady().
We just previously had "Drop time.monotonic() function, rename time.wallclock() to time.steady()" checked in a few weeks ago, and now we're renaming a variation on time.steady to time.monotonic? What's the next move?
I'm not paying close attention here but there's a lot of movement going on. Figuring out the API before we get too deep is probably a good idea.
Agreed with Brian. Obviously the API needs further discussion, judging by Victor's own multiple changes of mind on the subject. Regards Antoine.
On Sat, Mar 24, 2012 at 4:38 AM, Brian Curtin <brian@python.org> wrote:
On Fri, Mar 23, 2012 at 18:38, Yury Selivanov <yselivanov.ml@gmail.com> wrote:
On 2012-03-23, at 7:28 PM, Brian Curtin wrote:
This seems like it should have been a PEP, or maybe should become a PEP.
Why? AFAIK Victor just proposes to add two new functions: monotonic() and steady().
Need for PEPs is not determined by volume of content, but by amount of controversy and lack of clarity. Isn't it obvious that there's quite a bit of disagreement about the definitions of "monotonic" and "steady", and about whether these functions should be what they say they are or "best effort", and so on? +1 for a PEP.
We just previously had "Drop time.monotonic() function, rename time.wallclock() to time.steady()" checked in a few weeks ago, and now we're renaming a variation on time.steady to time.monotonic? What's the next move?
I'm not paying close attention here but there's a lot of movement going on. Figuring out the API before we get too deep is probably a good idea.
I have been following the thread but don't have the technical knowledge to be sure what's going on. What I have decided is that I won't be using any function named time.steady() or time.monotonic() because neither one seems likely to guarantee the property it's named for, and by the time I have a use case (I don't have one now, I'm just an habitual lurker) I'll have forgotten the conclusion of this thread, but not the deep feelings of FUD. To get me on board (not that there's any particular reason you should care, but just in case), you're going to need to respect EIBTI. By that I mean that a monotonic clock is monotonic, and if not available at instantiation, an Exception will be raised. Similarly for a steady clock. There is no such thing as "best effort" here for clocks with these names. The default clock should be best effort. If that is for some reason "expensive", then there should be a "time.windup_clock()" to provide an unreliable resource- conserving clock. FWIW, I understand that (1) A monotonic clock is one that never goes backwards. If precision allows, it should always go forwards (ie, repeated calls should always produce strictly larger time values). (2) A steady clock is strictly monotonic, and when a discrepancy against "true time" is detected (however that might happen), it slews its visible clock until the discrepancy is eliminated, so that one clock second always means something "close" to one second.
On 2012-03-23, at 7:25 PM, Victor Stinner wrote:
- time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward.
time.steady() is something like:
try: return time.monotonic() except (NotImplementError, OSError): return time.time()
Is the use of weak monotonic time so wide-spread in the stdlib that we need the 'steady()' function? If it's just two modules then it's not worth adding it. - Yury
time.steady() is something like:
try: return time.monotonic() except (NotImplementError, OSError): return time.time()
Is the use of weak monotonic time so wide-spread in the stdlib that we need the 'steady()' function? If it's just two modules then it's not worth adding it.
The Python standard library is not written to be used by Python itself, but by others. The try/except is a common pattern when applications use a monotonic clock. I suppose that quite all applications use this try/except pattern. I don't see what is the use case requiring a is truly monotonic clock. Victor
I don't see what is the use case requiring a is truly monotonic clock.
A clock that is purely monotonic may not be useful. However, people typically imply that it will have a certain minimum progress (seconds advanced/real seconds passed). Then you can use it for timeouts. Regards, Martin
Victor Stinner wrote: [...]
So we will have:
- time.time(): realtime, can be adjusted by the system administrator (manually) or automatically by NTP - time.clock(): monotonic clock on Windows, CPU time on UNIX - time.monotonic(): monotonic clock, its speed may or may not be adjusted by NTP but it only goes forward, may raise an OSError
This all sounds good to me. +1 up to this point. Question: under what circumstances will monotonic() exist but raise OSError?
- time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward.
What makes this "steady", given that it can be adjusted and it can go backwards? Doesn't sound steady to me. Is steady() merely a convenience function to avoid the user having to write something like this? try: mytimer = time.monotonic except AttributeError: mytimer = time.time or inline:
try: return time.monotonic() except (NotImplementError, OSError): return time.time()
Should that be (AttributeError, OSError) instead? -- Steven
Question: under what circumstances will monotonic() exist but raise OSError?
On Windows, OSError is raised if QueryPerformanceFrequency fails. Extract of Microsoft doc: "If the function fails, the return value is zero. To get extended error information, call GetLastError. For example, if the installed hardware does not support a high-resolution performance counter, the function fails." On UNIX, OSError is raised if clock_gettime(CLOCK_MONOTONIC) fails. Extract of clock_gettime() doc: "ERRORS EINVAL The clk_id specified is not supported on this system." It may occur if the libc exposes CLOCK_MONOTONIC but the kernel doesn't support it. I don't know if it can occur in practice.
- time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward.
What makes this "steady", given that it can be adjusted and it can go backwards? Doesn't sound steady to me.
In practice, it will be monotonic in most cases. "steady" name is used instead of "monotonic" because it may not be monotonic is other cases.
Is steady() merely a convenience function to avoid the user having to write something like this?
steady() remembers if the last call to monotonic failed or not. The real implementation is closer to something like: def steady(): if not steady.has_monotonic: return time.time() try: return time.monotonic() except (AttributeError, OSError): steady.has_monotonic = False return time.time() steady.has_monotonic = True Victor
Victor Stinner wrote:
Is steady() merely a convenience function to avoid the user having to write something like this?
steady() remembers if the last call to monotonic failed or not. The real implementation is closer to something like:
def steady(): if not steady.has_monotonic: return time.time() try: return time.monotonic() except (AttributeError, OSError): steady.has_monotonic = False return time.time() steady.has_monotonic = True
Does this mean that there are circumstances where monotonic will work for a while, but then fail? Otherwise, we would only need to check monotonic once, when the time module is first loaded, rather than every time it is called. Instead of the above: # global to the time module try: monotonic() except (NameError, OSError): steady = time else: steady = monotonic Are there failure modes where monotonic can recover? That is, it works for a while, then raises OSError, then works again on the next call. If so, steady will stop using monotonic and never try it again. Is that deliberate? -- Steven
Does this mean that there are circumstances where monotonic will work for a while, but then fail?
No. time.monotonic() always work or always fail. If monotonic() failed, steady() doesn't call it again.
Otherwise, we would only need to check monotonic once, when the time module is first loaded, rather than every time it is called. Instead of the above:
# global to the time module try: monotonic() except (NameError, OSError): steady = time else: steady = monotonic
I implemented steady differently to avoid the need of calling monotonic at Python startup. Calling monotonic at startup would be an extra useless system call. Victor
In http://mail.python.org/pipermail/python-dev/2012-March/118024.html Steven D'Aprano wrote:
What makes this "steady", given that it can be adjusted and it can go backwards?
It is best-effort for steady, but putting "best" in the name would be an attractive nuisance.
Is steady() merely a convenience function to avoid the user having to write something like this?
try: mytimer = time.monotonic except AttributeError: mytimer = time.time
That would still be worth doing. But I think the main point is that the clock *should* be monotonic, and *should* be as precise as possible. Given that it returns seconds elapsed (since an undefined start), perhaps it should be time.seconds() or even time.counter() -jJ -- If there are still threading problems with my replies, please email me with details, so that I can try to resolve them. -jJ
Victor Stinner wrote:
- time.clock(): monotonic clock on Windows, CPU time on UNIX
Actually, I think that is not correct. Or at least *was* not correct in 2006. http://bytes.com/topic/python/answers/527849-time-clock-going-backwards -- Steven
- time.clock(): monotonic clock on Windows, CPU time on UNIX
Actually, I think that is not correct. Or at least *was* not correct in 2006.
http://bytes.com/topic/python/answers/527849-time-clock-going-backwards
Oh, I was not aware of this issue. Do you suggest to not use QueryPerformanceCounter() on Windows to implement a monotonic clock? The python-monotonic-time project uses GetTickCount64(), or GetTickCount(), on Windows. GetTickCount64() was added to Windows Seven / Server 2008. GetTickCount() overflows after 49 days. QueryPerformanceCounter() has a better resolution than GetTickCount[64](). Victor
Victor Stinner wrote:
- time.clock(): monotonic clock on Windows, CPU time on UNIX
Actually, I think that is not correct. Or at least *was* not correct in 2006.
http://bytes.com/topic/python/answers/527849-time-clock-going-backwards
Oh, I was not aware of this issue. Do you suggest to not use QueryPerformanceCounter() on Windows to implement a monotonic clock?
I do not have an opinion on the best way to implement monotonic to guarantee that it actually is monotonic. -- Steven
Oh, I was not aware of this issue. Do you suggest to not use QueryPerformanceCounter() on Windows to implement a monotonic clock?
I do not have an opinion on the best way to implement monotonic to guarantee that it actually is monotonic.
I opened an issue: http://bugs.python.org/issue14397 Victor
On 3/23/2012 7:25 PM, Victor Stinner wrote: [snip]
- time.monotonic(): monotonic clock, its speed may or may not be adjusted by NTP but it only goes forward, may raise an OSError - time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward.
time.steady() is something like:
try: return time.monotonic() except (NotImplementError, OSError): return time.time()
I am surprised that a clock with the name time.steady() has a looser definition than one called time.monotonic(). To my mind a steady clock is by definition monotonic but a monotonic one may or may not be steady. Janzert
- time.monotonic(): monotonic clock, its speed may or may not be adjusted by NTP but it only goes forward, may raise an OSError - time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward.
I am surprised that a clock with the name time.steady() has a looser definition than one called time.monotonic(). To my mind a steady clock is by definition monotonic but a monotonic one may or may not be steady.
Do you suggest another name? Victor
On 3/24/2012 6:37 AM, Victor Stinner wrote:
- time.monotonic(): monotonic clock, its speed may or may not be adjusted by NTP but it only goes forward, may raise an OSError - time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward.
I am surprised that a clock with the name time.steady() has a looser definition than one called time.monotonic(). To my mind a steady clock is by definition monotonic but a monotonic one may or may not be steady.
Do you suggest another name?
Victor
I can't think of a word or short phrase that adequately describes that behavior, no. But that may just be because I also don't see any use case for it either. To me the more useful function would be one that used the OS monotonic clock when available and failing that used the realtime clock but cached the previous returned value and ensured that all values returned obeyed the monotonic property still. But I don't see why that function shouldn't just be time.monotonic(). Janzert
On Fri, Mar 23, 2012 at 4:25 PM, Victor Stinner <victor.stinner@gmail.com> wrote:
Hi,
time.steady(strict=True) looks to be confusing for most people, some of them don't understand the purpose of the flag and others don't like a flag changing the behaviour of the function.
I propose to replace time.steady(strict=True) by time.monotonic(). That would avoid the need of an ugly NotImplementedError: if the OS has no monotonic clock, time.monotonic() will just not exist.
So we will have:
- time.time(): realtime, can be adjusted by the system administrator (manually) or automatically by NTP - time.clock(): monotonic clock on Windows, CPU time on UNIX - time.monotonic(): monotonic clock, its speed may or may not be adjusted by NTP but it only goes forward, may raise an OSError - time.steady(): monotonic clock or the realtime clock, depending on what is available on the platform (use monotonic in priority). may be adjusted by NTP or the system administrator, may go backward.
Please don't use the word "steady" for something different from what C++ means by it. C++'s term means "may not be adjusted at all, even by NTP; proceeds at as close to the rate of real time as the system can manage" (paraphrased). If the consensus in the Python community is that a C++-style "steady" clock is unnecessary, then feel free not to define it. If the consensus is that "monotonic" already means everything C++ means by "steady", that's fine with me too. I mentioned it because I thought it might be worth looking at what other languages were doing in this space, not because I thought it was a nice word that you should attach your own definitions to. Jeffrey
participants (11)
-
"Martin v. Löwis"
-
Antoine Pitrou
-
Brian Curtin
-
Janzert
-
Jeffrey Yasskin
-
Jim J. Jewett
-
Lennart Regebro
-
Stephen J. Turnbull
-
Steven D'Aprano
-
Victor Stinner
-
Yury Selivanov