[Python-Dev] PEP 418: Add monotonic clock
Nick Coghlan
ncoghlan at gmail.com
Wed Mar 28 17:35:46 CEST 2012
On Thu, Mar 29, 2012 at 1:02 AM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:
> On 2012-03-28, at 10:45 AM, Nick Coghlan wrote:
>
>> On Thu, Mar 29, 2012 at 12:27 AM, Yury Selivanov
>> <yselivanov.ml at gmail.com> wrote:
>>> What if system time jumps 1 year back? We'll have the same
>>> monotonic time returned for this whole year?
>>>
>>> I don't think we should even try to emulate any of OS-level
>>> functionality.
>>
>> You have to keep in mind the alternative here: falling back to an
>> *unconditioned* time.time() value (which is the status quo, and
>> necessary to preserve backwards compatibility). That will break just
>> as badly in that scenario and is precisely the reason that the OS
>> level monotonic functionality is desirable in the first place.
>
> Well, my argumentation is that you either have some code that depends
> on monotonic time and can't work without it, or you have a code that
> can work with any time (and only precision matters). Maybe I'm wrong.
You're wrong.
The primary use case for the new time.monotonic() function is to
replace *existing* uses of time.time() in the standard library (mostly
related to timeouts) that are currently vulnerable to clock adjustment
related bugs. This real, concrete use case has been lost in some of
the abstract theoretical discussions that have been going on this
thread.
We can't lose sight of the fact that using a system clock that is
vulnerable to clock adjustment bugs to handle timeouts and
benchmarking in Python has worked just fine for 20+ years. Using a
monotonic clock instead is *better*, but it's far from essential,
since clock adjustments that are big enough and poorly timed enough to
cause real problems are fortunately a very rare occurrence.
So, the primary use case is that we want to replace many of the
time.time() calls in the standard library with time.monotonic() calls.
To avoid backwards compatibility problems in the cross-platform
support, that means time.monotonic() *must be available on every
platform that currently provides time.time()*.
This is why Victor's original proposal was that time.monotonic()
simply fall back to time.time() if there was no OS level monotonic
clock available. The intended use cases are using time.time() *right
now* and have been doing so for years, so it is clearly an acceptable
fallback for those cases. People (rightly, in my opinion) objected to
the idea of time.monotonic() failing to guarantee monotonicity, thus
the proposal to enforce at least a basic level of monotonicity through
caching of the last returned value. I agree completely that this dumb
caching solution doesn't solve any of the original problems with
time.time() that make a time.monotonic() function desirable, but it
isn't meant to. It's only meant to provide graceful degradation to
something that is *no worse than the current behaviour when using
time.time() in Python 3.2* while still respecting the property of
monotonicity for the new API. Yes, it's an ugly hack, but it is a
necessary fallback to avoid accidental regressions in our
cross-platform support.
For the major platforms (i.e. *nix, Mac OS X, Windows), there *will*
be an OS level monotonic clock available, thus using time.monotonic()
will have the desired effect of protecting from clocks being adjusted
backwards. For other platforms, the behaviour (and vulnerabilities)
will be essentially unchanged from the Python 3.2 approach (i.e. using
time.time() with no monotonicity guarantees at all).
However, some 3.3+ applications may want to be stricter about their
behaviour and either bail out completely or fall back to an unfiltered
time.time() call if an OS-level monotonic clock is not available. For
those, it makes sense to expose time.os_monotonic() directly (and only
if it is available), thus allowing those developers to make up their
own mind instead of accepting the cross-platform fallback in
time.monotonic().
Yes, you can get the exact same effect with the "monotonic()" and
"try_monotonic()" naming scheme, but why force the standard library
(and anyone else wanting to upgrade from time.time() without harming
cross-platform support) to use such an ugly name when the
"os_monotonic" and "monotonic" naming scheme provides a much neater
alternative?
Regards,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-Dev
mailing list