]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-63207: Use GetSystemTimePreciseAsFileTime() in time.time() (#116822)
authorVictor Stinner <vstinner@python.org>
Mon, 18 Mar 2024 16:13:01 +0000 (17:13 +0100)
committerGitHub <noreply@github.com>
Mon, 18 Mar 2024 16:13:01 +0000 (17:13 +0100)
Doc/whatsnew/3.13.rst
Misc/NEWS.d/next/Library/2024-03-14-17-21-25.gh-issue-63207.LV16SL.rst [new file with mode: 0644]
Python/pytime.c

index a48db949d8f401259d6f97b2d85ad74b68e539cf..b665e6f1c859157a608f4b1567e5666649847c47 100644 (file)
@@ -570,6 +570,12 @@ time
   instead of the ``GetTickCount64()`` clock which has a resolution of 15.6 ms.
   (Contributed by Victor Stinner in :gh:`88494`.)
 
+* On Windows, :func:`time.time()` now uses the
+  ``GetSystemTimePreciseAsFileTime()`` clock to have a resolution better
+  than 1 us, instead of the ``GetSystemTimeAsFileTime()`` clock which has a
+  resolution of 15.6 ms.
+  (Contributed by Victor Stinner in :gh:`63207`.)
+
 
 tkinter
 -------
diff --git a/Misc/NEWS.d/next/Library/2024-03-14-17-21-25.gh-issue-63207.LV16SL.rst b/Misc/NEWS.d/next/Library/2024-03-14-17-21-25.gh-issue-63207.LV16SL.rst
new file mode 100644 (file)
index 0000000..1f77555
--- /dev/null
@@ -0,0 +1,4 @@
+On Windows, :func:`time.time()` now uses the
+``GetSystemTimePreciseAsFileTime()`` clock to have a resolution better than 1
+us, instead of the ``GetSystemTimeAsFileTime()`` clock which has a resolution
+of 15.6 ms. Patch by Victor Stinner.
index 45be6a3dbd334133aea786e68566afa43990889e..d5b38047b6db31a76ad10f05a50a190a05821e49 100644 (file)
 #endif
 
 
+#ifdef MS_WINDOWS
+static _PyTimeFraction py_qpc_base = {0, 0};
+
+// Forward declaration
+static int py_win_perf_counter_frequency(_PyTimeFraction *base, int raise_exc);
+#endif
+
+
 static PyTime_t
 _PyTime_GCD(PyTime_t x, PyTime_t y)
 {
@@ -895,7 +903,7 @@ py_get_system_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
     FILETIME system_time;
     ULARGE_INTEGER large;
 
-    GetSystemTimeAsFileTime(&system_time);
+    GetSystemTimePreciseAsFileTime(&system_time);
     large.u.LowPart = system_time.dwLowDateTime;
     large.u.HighPart = system_time.dwHighDateTime;
     /* 11,644,473,600,000,000,000: number of nanoseconds between
@@ -904,18 +912,17 @@ py_get_system_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
     PyTime_t ns = large.QuadPart * 100 - 11644473600000000000;
     *tp = ns;
     if (info) {
-        DWORD timeAdjustment, timeIncrement;
-        BOOL isTimeAdjustmentDisabled, ok;
+        // GetSystemTimePreciseAsFileTime() is implemented using
+        // QueryPerformanceCounter() internally.
+        if (py_qpc_base.denom == 0) {
+            if (py_win_perf_counter_frequency(&py_qpc_base, raise_exc) < 0) {
+                return -1;
+            }
+        }
 
-        info->implementation = "GetSystemTimeAsFileTime()";
+        info->implementation = "GetSystemTimePreciseAsFileTime()";
         info->monotonic = 0;
-        ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
-                                     &isTimeAdjustmentDisabled);
-        if (!ok) {
-            PyErr_SetFromWindowsErr(0);
-            return -1;
-        }
-        info->resolution = timeIncrement * 1e-7;
+        info->resolution = _PyTimeFraction_Resolution(&py_qpc_base);
         info->adjustable = 1;
     }
 
@@ -1063,16 +1070,15 @@ py_get_win_perf_counter(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
 {
     assert(info == NULL || raise_exc);
 
-    static _PyTimeFraction base = {0, 0};
-    if (base.denom == 0) {
-        if (py_win_perf_counter_frequency(&base, raise_exc) < 0) {
+    if (py_qpc_base.denom == 0) {
+        if (py_win_perf_counter_frequency(&py_qpc_base, raise_exc) < 0) {
             return -1;
         }
     }
 
     if (info) {
         info->implementation = "QueryPerformanceCounter()";
-        info->resolution = _PyTimeFraction_Resolution(&base);
+        info->resolution = _PyTimeFraction_Resolution(&py_qpc_base);
         info->monotonic = 1;
         info->adjustable = 0;
     }
@@ -1088,7 +1094,7 @@ py_get_win_perf_counter(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
                   "LONGLONG is larger than PyTime_t");
     ticks = (PyTime_t)ticksll;
 
-    *tp = _PyTimeFraction_Mul(ticks, &base);
+    *tp = _PyTimeFraction_Mul(ticks, &py_qpc_base);
     return 0;
 }
 #endif  // MS_WINDOWS