This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: precise time.time() under Windows 8: use GetSystemTimePreciseAsFileTime
Type: enhancement Stage:
Components: Library (Lib), Windows Versions: Python 3.11
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: akira, belopolsky, eryksun, lemburg, pitrou, steve.dower, tim.golden, tim.peters, vstinner, zach.ware
Priority: low Keywords: patch

Created on 2013-09-12 19:44 by pitrou, last changed 2022-04-11 14:57 by admin.

Files
File name Uploaded Description Edit
time_precise.patch vstinner, 2015-07-31 22:01 review
Messages (9)
msg197538 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-09-12 19:44
For whoever is interested: Windows 8 apparently has a new API named GetSystemTimePreciseAsFileTime which returns the system API with a much better resolution than GetSystemTimeAsFileTime does ("The GetSystemTimePreciseAsFileTime function retrieves the current system date and time with the highest possible level of precision (<1us)").
http://msdn.microsoft.com/en-us/library/windows/desktop/hh706895%28v=vs.85%29.aspx

(spawned from this topic on the tulip mailing-list: https://groups.google.com/forum/#!topic/python-tulip/vX9vOZB1FOI )
msg197539 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-09-12 20:29
time.time() is sometimes used in performance critical code. Is GetSystemTimePreciseAsFileTime() as fast as GetSystemTimeAsFileTime()?

Linux has the opposite: CLOCK_REALTIME_COARSE. This clock is less accurate but may be faster.
http://lwn.net/Articles/342018/
msg197541 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-09-12 20:32
"GetSystemTimePreciseAsFileTime() has very little overhead; the new function is even a little faster than GetSystemTimeAsFileTime(), a call takes a few ten nanoseconds."

from http://www.windowstimestamp.com/description#C_2
msg224358 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-07-30 22:32
My patch for the issue #22043 replaces the _PyTime_timeval structure (10^-6 second resolution, 1 us) with a _PyTime_timespec structure (10^-9 second resolution, 1 ns). It may help for this issue.
msg247024 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-07-21 10:50
Python 3.5 has a new C function _PyTime_GetSystemClock() which uses the new _PyTime_t type. It now has a resolution of 1 nanosecond.

Sorry, I don't have Windows 8 at home, so I cannot work on this issue.

I guess that we should check at runtime if GetSystemTimePreciseAsFileTime() is available, as we did for GetTickCount64() in the past:

hKernel32 = GetModuleHandleW(L"KERNEL32");
*(FARPROC*)&Py_GetTickCount64 = GetProcAddress(hKernel32,
                                               "GetTickCount64");

Is there any Windows developer interested to write a short patch to implement it?
msg247778 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-07-31 22:01
Good news! I got a new fresh Windows 8.1 VM with Visual Studio 2015. I'm now able to work on this issue.

I wrote a patch: time_precise.patch.

Resolution computed in Python by https://hg.python.org/peps/file/tip/pep-0418/clock_resolution.py:

GetSystemTimePreciseAsFileTime(): 715 ns
GetSystemTimeAsFileTime(): 14 ms

Obviously, the resolution is better...

GetSystemTimePreciseAsFileTime() uses internally the QueryPerformanceCounter() so I chose to use QueryPerformanceFrequency() to fill time.get_clock_info('time').resolution, same code than time.get_clock_info('perf_counter').resolution
msg247779 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-07-31 22:05
Note: GetSystemTimePreciseAsFileTime() is restricted to desktop applications.

The windowstimestamp.com has a warning on this function:

http://www.windowstimestamp.com/description

"""
2.1.4.2.  Desktop Applications: GetSystemTimePreciseAsFileTime()

(...)
The function shall also be used with care when a system time adjustment is active. Current Windows versions treat the performance counter frequency as a constant. The high resolution of GetSystemTimePreciseAsFileTime() is derived from the performance counter value at the time of the call and the performance counter frequency. However, the performance counter frequency should be corrected during system time adjustments to adapt to the modified progress in time. Current Windows versions don't do this. The obtained microsecond part may be severely affected when system time adjustments are active. Seconds may consist of more or less than 1.000.000 microseconds. Microsoft may or not fix this in one of the next updates/versions.
(...)
As of May, 2015 the inaccuracy of GetSystemTimePreciseAsFileTime() during system time adjustments persists for the preview versions of Windows 10.
"""

Is it ok to switch to GetSystemTimePreciseAsFileTime() for Python time.time()?
msg247808 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2015-08-01 12:46
What are the expected benefits from changing? Just a higher resolution? I'm not sure that's worth anything if it's inaccurate.
msg395767 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2021-06-13 22:48
> What are the expected benefits from changing? Just a higher 
> resolution? I'm not sure that's worth anything if it's inaccurate.

GetSystemTimePreciseAsFileTime() returns an accurate timestamp, which is the current system time plus the difference between the current value of the performance counter and its value when the system time was last updated. This can't be replicated simply with separate calls to GetSystemTimeAsFileTime() and QueryPerformanceCounter(). It relies on the following undocumented fields in the KUSER_SHARED_DATA record: BaselineSystemTimeQpc, QpcSystemTimeIncrement, and QpcSystemTimeIncrementShift. 

The system uses a similar procedure in QueryInterruptTimePrecise() to extend the precision of QueryInterruptTime(). Ditto for QueryUnbiasedInterruptTime() vs QueryUnbiasedInterruptTimePrecise().

> "GetSystemTimePreciseAsFileTime() has very little overhead; the new 
> function is even a little faster than GetSystemTimeAsFileTime(), a 
> call takes a few ten nanoseconds."

The above claim was corrected back in 2014. GetSystemTimePreciseAsFileTime() is considerably more expensive than GetSystemTimeAsFileTime(). It costs about 10 times more on a system that supports an invariant TSC. It would be more expensive on an older system that use the chipset's HPET or ACPI PM timer. That said, I doubt this matters very much when calling time.time() in interpreted code. It's a difference measured in tens of nanoseconds.
History
Date User Action Args
2022-04-11 14:57:50adminsetgithub: 63207
2021-06-13 22:48:09eryksunsetnosy: + eryksun

messages: + msg395767
versions: + Python 3.11, - Python 3.6
2015-08-01 12:46:06steve.dowersetmessages: + msg247808
2015-07-31 22:05:18vstinnersetmessages: + msg247779
2015-07-31 22:01:33vstinnersetfiles: + time_precise.patch
keywords: + patch
messages: + msg247778
2015-07-21 10:50:56vstinnersetmessages: + msg247024
versions: + Python 3.6, - Python 3.5
2015-07-21 04:43:29akirasetnosy: + akira
2014-07-30 23:45:51vstinnersettitle: precise time.time() under Windows 8 -> precise time.time() under Windows 8: use GetSystemTimePreciseAsFileTime
2014-07-30 22:32:54vstinnersetmessages: + msg224358
2014-07-30 22:05:54BreamoreBoysetnosy: + tim.golden, zach.ware, steve.dower

versions: + Python 3.5, - Python 3.4
2013-09-12 20:32:23pitrousetmessages: + msg197541
2013-09-12 20:29:32vstinnersetmessages: + msg197539
2013-09-12 19:44:34pitroucreate