[Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
Guido van Rossum
guido at python.org
Fri Mar 30 23:35:29 CEST 2012
On Fri, Mar 30, 2012 at 1:52 PM, Guido van Rossum <guido at python.org> wrote:
> On Fri, Mar 30, 2012 at 1:21 PM, Victor Stinner
> <victor.stinner at gmail.com> wrote:
>> Windows provides two main monotonic clocks: QueryPerformanceCounter()
>> and GetTickCount(). QueryPerformanceCounter() has a good accuracy (0.3
>> ns - 5 ns) but has various issues and is know to not have a steady
>> rate. GetTickCount() has a worse accuracy (1 ms - 15 ms) but is more
>> stable and behave better on system suspend/resume.
>>
>> The glib library prefers GetTickCount() over QueryPerformanceCounter()
>> for its g_get_monotonic_time() because "The QPC timer has too many
>> issues to be used as is."
>> Ihttp://mail.gnome.org/archives/commits-list/2011-November/msg04589.html
>>
>> The Qt library tries QueryPerformanceCounter() but may fallback to
>> GetTickCount() if it is not available.
>>
>> python-monotonic-time only uses GetTickCount() or GetTickCount64().
>>
>> It is important to decide which clock is used for the Python
>> time.monotonic() because it may change the design of the PEP 418. If
>> we use GetTickCount() for time.monotonic(), we should use
>> QueryPerformanceCounter() for time.highres(). But in this case, it
>> means that time.highres() is not a simple "try monotonic or falls back
>> to system time", but may use a different clock with an higher
>> resolution. So we might add a third function for the "try monotonic or
>> falls back to system time" requirement.
>>
>> Python implements time.clock() using QueryPerformanceCounter() on Windows.
>
> Oh dear. I really want to say that 15 ms is good enough. Some possible
> exceptions I can think of:
>
> - Profiling. But this really wants to measure CPU time anyways, and it
> already uses a variety of hacks and heuristics to pick the best timer,
> so I don't really care.
>
> - Certain algorithms for thread (or even process?) communication might
> benefit from being able to set very short timeouts. But it seems you
> can just specify a timeout when waiting for a lock and it will be
> taken care of. So probably a non-use-case.
>
> So I think I still prefer GetTickCount*() over QueryPerformanceCounter().
>
> And this is another reason why I don't like highres as a name -- as I
> said, I really prefer to have just two new functions, one that's a
> decent OS-provided timer that isn't affected by wall clock
> adjustments, if there is one, and the other strictly an alias for that
> one with a fallback to time.time() if there isn't one. Having two
> different OS-provided timers with different pros and cons will just
> make it too hard for users to decide, and hence we'll see a higher
> rate of using the wrong timer.
>
> (In fact, this even argues against having both the timer with fallback
> and the timer without fallback. So maybe we should just have a single
> timer function, *with* fallback, and a separate mechanism to inquire
> its properties.)
And disagreeing with myself, I just found myself using a tool for RPC
analytics that displays times in msec, and the times are often between
1 and 20 msec. Here a 15 msec timer would be horrible, and I see no
alternative but to use QPC()... (Well, if the tool ran on Windows,
which it doesn't. :-)
Can we tell what the accuracy of GetTickCount*() is when we first
request the time, and decode then?
Can you go into more detail about QPC()'s issues? What is unsteady
about its rate?
--
--Guido van Rossum (python.org/~guido)
More information about the Python-Dev
mailing list