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

Guido van Rossum guido at python.org
Fri Mar 30 22:52:50 CEST 2012


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.)

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


More information about the Python-Dev mailing list