STINNER Victor <vstin...@python.org> added the comment:

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

----------

_______________________________________
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