Ryan Hileman <lunixbo...@gmail.com> added the comment:

I found these two references:
- 
https://stackoverflow.com/questions/35601880/windows-timing-drift-of-performancecounter-c
- https://bugs.python.org/issue10278#msg143209

Which suggest QueryPerformanceCounter() may be bad because it can drift. 
However, these posts are fairly old and the StackOverflow post also says the 
drift is small on newer hardware / Windows.

Microsoft's current stance is that QueryPerformanceCounter() is good: 
https://docs.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps

> Guidance for acquiring time stamps
> Windows has and will continue to invest in providing a reliable and efficient 
> performance counter. When you need time stamps with a resolution of 1 
> microsecond or better and you don't need the time stamps to be synchronized 
> to an external time reference, choose QueryPerformanceCounter

I looked into how a few other languages provide monotonic time on Windows:

Golang seems to read the interrupt time (presumably equivalent to 
QueryInterruptTime) directly by address. 
https://github.com/golang/go/blob/a3868028ac8470d1ab7782614707bb90925e7fe3/src/runtime/sys_windows_amd64.s#L499

Rust uses QueryPerformanceCounter: 
https://github.com/rust-lang/rust/blob/38ec87c1885c62ed8c66320ad24c7e535535e4bd/library/std/src/time.rs#L91

V8 uses QueryPerformanceCounter after checking for old CPUs: 
https://github.com/v8/v8/blob/dc712da548c7fb433caed56af9a021d964952728/src/base/platform/time.cc#L672

Ruby uses QueryPerformanceCounter: 
https://github.com/ruby/ruby/blob/44cff500a0ad565952e84935bc98523c36a91b06/win32/win32.c#L4712

C# implements QueryPerformanceCounter on other platforms using CLOCK_MONOTONIC, 
indicating that they should be roughly equivalent: 
https://github.com/dotnet/runtime/blob/01b7e73cd378145264a7cb7a09365b41ed42b240/src/coreclr/pal/src/misc/time.cpp#L175

Swift originally used QueryPerformanceCounter, but switched to 
QueryUnbiasedInterruptTime() because they didn't want to count time the system 
spent asleep: 
https://github.com/apple/swift-corelibs-libdispatch/commit/766d64719cfdd07f97841092bec596669261a16f

------

Note that none of these languages use GetTickCount64(). Swift is an interesting 
counter point, and I noticed QueryUnbiasedInterruptTime() is available on 
Windows 8 while QueryInterruptTime() is new as of Windows 10. The "Unbiased" 
just refers to whether it advances during sleep.

I'm not actually sure whether time.monotonic() in Python counts time spent 
asleep, or whether that's desirable. Some kinds of timers using monotonic time 
should definitely freeze during sleep so they don't cause a flurry of activity 
on wake, but others definitely need to roughly track wall clock time, even 
during sleep.

Perhaps the long term answer would be to introduce separate "asleep" and 
"awake" monotonic clocks in Python, and possibly deprecate perf_counter() if 
it's redundant after this (as I think it's aliased to monotonic() on 
non-Windows platforms anyway).

----------
title: time.monotonic() should use QueryPerformanceCounter() on Windows -> 
time.monotonic() should use a different clock source on Windows

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue44328>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to