[Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?

Guido van Rossum guido at python.org
Sat Mar 31 01:46:13 CEST 2012


Given the amount of disagreement I sense, I think we'll need to wait
for more people to chime in.

On Fri, Mar 30, 2012 at 3:47 PM, Victor Stinner
<victor.stinner at gmail.com> wrote:
>> Can you go into more detail about QPC()'s issues?
>
> Yes, see the PEP:
> http://www.python.org/dev/peps/pep-0418/#windows-queryperformancecounter
>
>> What is unsteady about its rate?
>
> Hum, I read that you can expect a drift between QPC and GetTickCount.
> I don't have exact numbers. There are also issues with power-saving.
> When the CPU frequency changes, the frequency of the TSC is also
> impacted on some processors (others provide a TSC at a fixed
> frequency).

And how does that impact teh various use cases? (There still isn't
enough about use cases in the PEP. Thank you very much though for
adding all those details about the various platform clocks.)

> 2012/3/30 Guido van Rossum <guido at python.org>:
>> Possibly we really do need two timers, one for measuring short
>> intervals and one for measuring long intervals? Perhaps we can use
>> this to decide on the names?
>
> "short" and "long" interval is not how these clocks should be defined.

Why not?

> I prefer use cases:
>
>  * time.highres() should be used for profiling and benchmarking
>  * time.monotonic() should be used for a scheduler and timeout

So if I want to schedule something a week in the future, what should I
use? monotonic() or time()? And can you explain the reason for your
answer? What about an hour or a day? Or a month or a year?

> time.monotonic() rate should be as steady as possible, its stability
> is more important than its accuracy. time.highres() should provide the
> clock with the best accuracy. Both clocks may have an undefined
> starting point.

So what kind of drift is acceptable for each?

>> Anyway, the more I think about it, the more I believe these functions
>> should have very loose guarantees, and instead just cater to common
>> use cases -- availability of a timer with minimal fuss is usually more
>> important than the guarantees. So forget the idea about one version
>> that falls back to time.time() and another that doesn't -- just always
>> fall back to time.time(), which is (almost) always better than
>> failing.
>
> I disagree. Python must provide a truly monotonic clock, even it is
> not truly monotonic by default.

Why?

> If we want to provide a convenient "monotonic or falllback to system
> time", there are different options: add a dedicated function (e.g.
> time.try_monotonic()) or add a parameter to enable or disable the
> fallback. Between these two options, I prefer the parameter because it
> avoids the creation of a new function. Even if I now agree that a
> truly monotonic clock is required, I also agree with Guido: the most
> common case is to use a fallback.
>
> I suggest this API: time.monotonic(fallback=True).

But this goes against the idea of "A keyword argument that gets passed
as a constant in the caller is usually poor API."

And it would encourage the creation of trivial lambdas just to call
the timer with this flag, since a universal API is a timer function
that takes no arguments.

> Another option is to not provide a "monotonic or falllback to system
> time" clock and write an explicit try/except where you need a
> fallback. I don't like this solution because time.monotonic() might
> fail at runtime with OSError, and so catching AttributeError is not
> enough...

Check out Cameron Simpson's proposal earlier in this thread. If we
really are going to have a variety of functions and fallback options,
his approach may be the best.

>> Then we can design a separate inquiry API (doesn't have to be complex
>> as long as it's extensible -- a dict or object with a few predefined
>> keys or attributes sounds good enough) for apps that want to know more
>> about how the timer they're using is actually implemented.
>
> Sometimes, it does matter which exact OS clock is used.

When is that?

> The QElapsedTime class of the Qt libraries has an attribute (an enum)
> describing which clock is used. We can give the name of the function
> and the resolution. In some specific cases, we are able to read the
> accuracy (ex: GetTickCount). The accuracy may change at runtime (at
> least for GetTickCount).

That sounds like a fine API.

> Should I include such new function in the PEP, or can it be discussed
> (later) in a separated thread?

FWIW, I prefer a single thread devoted to all aspects of this PEP.

> --
>
> I don't want to only provide time.monotonic() which would fallback if
> no monotonic clock is available, because we would be unable to tell if
> the clock is monotonic or not.

There could be a separate inquiry API.

> See the implementation in the PEP: the
> "try monotonic or fallback" function may use a different clock at each
> call, and so may be monotonic at startup and then becomes
> non-monotonic.

No, it should never switch implementations once it has chosen. That's
just asking for trouble. If it can become non-monotonic it just isn't
monotonic. Again, Cameron Simpson's idea might help here.

> An alternative is time.monotonic() returning (time, is_monotonic) but
> this is an ugly API. You cannot simply write:
>   a=time.monotonic(); benchmark(); b=time.monotonic(); print(b-a)
> because it raises a TypeError on b-a.

Agreed, that's not useful. It should be a constant property (constant
within one process).

> --
>
> I will update the PEP to describe my new proposition.

Thanks. Please pay specific attention to my why/where/when questions above.

-- 
--Guido van Rossum (python.org/~guido)


More information about the Python-Dev mailing list