Message395681
Changing is clock is a tricky. There are many things to consider:
* Is it really monotonic in all cases?
* Does it have a better resolution than the previous clock?
* Corner cases: does it include time spent in time.sleep() and while the system is suspended?
* etc.
--
When I designed PEP 418 (in 2012), QueryPerformanceCounter() was not reliable:
"It has a much higher resolution, but has lower long term precision than GetTickCount() and timeGetTime() clocks. For example, it will drift compared to the low precision clocks."
https://www.python.org/dev/peps/pep-0418/#windows-queryperformancecounter
And there were a few bugs like: "The performance counter value may unexpectedly leap forward because of a hardware bug".
A Microsoft blog article explains that users wanting a steady clock with precision higher than GetTickCount() should interpolate GetTickCount() using QueryPerformanceCounter(). If I recall correctly, this is what Firefox did for instance.
Eryk: "That said, Windows 10 also provides QueryInterruptTimePrecise(), which is a hybrid solution. It uses the performance counter to interpolate a timestamp between interrupts. I'd prefer to use this for time.monotonic() instead of QPC, if it's available via GetProcAddress()."
Oh, good that they provided an implementation for that :-)
--
> V8 uses QueryPerformanceCounter after checking for old CPUs: https://github.com/v8/v8/blob/dc712da548c7fb433caed56af9a021d964952728/src/base/platform/time.cc#L672
It uses CPUID to check for "non stoppable time stamp counter":
https://github.com/v8/v8/blob/master/src/base/cpu.cc
// Check if CPU has non stoppable time stamp counter.
const unsigned parameter_containing_non_stop_time_stamp_counter = 0x80000007;
if (num_ext_ids >= parameter_containing_non_stop_time_stamp_counter) {
__cpuid(cpu_info, parameter_containing_non_stop_time_stamp_counter);
has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0;
}
Maybe we use such check in Python: use GetTickCount() on old CPUs, or QueryPerformanceCounter() otherwise. MSVC provides the __cpuid() function:
https://docs.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=msvc-160
--
> Swift originally used QueryPerformanceCounter, but switched to QueryUnbiasedInterruptTime() because they didn't want to count time the system spent asleep
Oh, I recall that it was a tricky question. The PEP 418 simply says:
"The behaviour of clocks after a system suspend is not defined in the documentation of new functions."
See "Include Sleep" and "Include Suspend" columns of my table:
https://www.python.org/dev/peps/pep-0418/#monotonic-clocks |
|
Date |
User |
Action |
Args |
2021-06-12 08:47:53 | vstinner | set | recipients:
+ vstinner, paul.moore, belopolsky, tim.golden, zach.ware, eryksun, steve.dower, p-ganssle, lunixbochs2 |
2021-06-12 08:47:53 | vstinner | set | messageid: <1623487673.94.0.473781652926.issue44328@roundup.psfhosted.org> |
2021-06-12 08:47:53 | vstinner | link | issue44328 messages |
2021-06-12 08:47:53 | vstinner | create | |
|