Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3df5c68

Browse files
authored
bpo-37205: time.perf_counter() and time.monotonic() are system-wide (GH-23284)
time.perf_counter() on Windows and time.monotonic() on macOS are now system-wide. Previously, they used an offset computed at startup to reduce the precision loss caused by the float type. Use time.perf_counter_ns() and time.monotonic_ns() added in Python 3.7 to avoid this precision loss.
1 parent aa01011 commit 3df5c68

3 files changed

Lines changed: 43 additions & 21 deletions

File tree

Doc/library/time.rst

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ Functions
166166
Return the time of the specified clock *clk_id*. Refer to
167167
:ref:`time-clock-id-constants` for a list of accepted values for *clk_id*.
168168

169+
Use :func:`clock_gettime_ns` to avoid the precision loss caused by the
170+
:class:`float` type.
171+
169172
.. availability:: Unix.
170173

171174
.. versionadded:: 3.3
@@ -185,6 +188,9 @@ Functions
185188
Set the time of the specified clock *clk_id*. Currently,
186189
:data:`CLOCK_REALTIME` is the only accepted value for *clk_id*.
187190

191+
Use :func:`clock_settime_ns` to avoid the precision loss caused by the
192+
:class:`float` type.
193+
188194
.. availability:: Unix.
189195

190196
.. versionadded:: 3.3
@@ -273,10 +279,17 @@ Functions
273279
The reference point of the returned value is undefined, so that only the
274280
difference between the results of consecutive calls is valid.
275281

282+
Use :func:`monotonic_ns` to avoid the precision loss caused by the
283+
:class:`float` type.
284+
276285
.. versionadded:: 3.3
286+
277287
.. versionchanged:: 3.5
278288
The function is now always available and always system-wide.
279289

290+
.. versionchanged:: 3.10
291+
On macOS, the function is now system-wide.
292+
280293

281294
.. function:: monotonic_ns() -> int
282295

@@ -295,8 +308,14 @@ Functions
295308
point of the returned value is undefined, so that only the difference between
296309
the results of consecutive calls is valid.
297310

311+
Use :func:`perf_counter_ns` to avoid the precision loss caused by the
312+
:class:`float` type.
313+
298314
.. versionadded:: 3.3
299315

316+
.. versionchanged:: 3.10
317+
On Windows, the function is now system-wide.
318+
300319
.. function:: perf_counter_ns() -> int
301320

302321
Similar to :func:`perf_counter`, but return time as nanoseconds.
@@ -317,6 +336,9 @@ Functions
317336
returned value is undefined, so that only the difference between the results
318337
of consecutive calls is valid.
319338

339+
Use :func:`process_time_ns` to avoid the precision loss caused by the
340+
:class:`float` type.
341+
320342
.. versionadded:: 3.3
321343

322344
.. function:: process_time_ns() -> int
@@ -581,6 +603,17 @@ Functions
581603
:class:`struct_time` object is returned, from which the components
582604
of the calendar date may be accessed as attributes.
583605

606+
Use :func:`time_ns` to avoid the precision loss caused by the :class:`float`
607+
type.
608+
609+
610+
.. function:: time_ns() -> int
611+
612+
Similar to :func:`~time.time` but returns time as an integer number of nanoseconds
613+
since the epoch_.
614+
615+
.. versionadded:: 3.7
616+
584617

585618
.. function:: thread_time() -> float
586619

@@ -595,6 +628,9 @@ Functions
595628
returned value is undefined, so that only the difference between the results
596629
of consecutive calls in the same thread is valid.
597630

631+
Use :func:`thread_time_ns` to avoid the precision loss caused by the
632+
:class:`float` type.
633+
598634
.. availability:: Windows, Linux, Unix systems supporting
599635
``CLOCK_THREAD_CPUTIME_ID``.
600636

@@ -608,13 +644,6 @@ Functions
608644
.. versionadded:: 3.7
609645

610646

611-
.. function:: time_ns() -> int
612-
613-
Similar to :func:`~time.time` but returns time as an integer number of nanoseconds
614-
since the epoch_.
615-
616-
.. versionadded:: 3.7
617-
618647
.. function:: tzset()
619648

620649
Reset the time conversion rules used by the library routines. The environment
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
:func:`time.perf_counter()` on Windows and :func:`time.monotonic()` on macOS
2+
are now system-wide. Previously, they used an offset computed at startup to
3+
reduce the precision loss caused by the float type. Use
4+
:func:`time.perf_counter_ns()` and :func:`time.monotonic_ns()` added in Python
5+
3.7 to avoid this precision loss.

Python/pytime.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#if defined(__APPLE__)
77
#include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */
88

9-
#if defined(__APPLE__) && defined(__has_builtin)
9+
#if defined(__APPLE__) && defined(__has_builtin)
1010
# if __has_builtin(__builtin_available)
1111
# define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
1212
# endif
@@ -730,7 +730,7 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
730730
}
731731

732732
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
733-
} else {
733+
} else {
734734
#endif
735735

736736
#endif
@@ -822,7 +822,6 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
822822

823823
#elif defined(__APPLE__)
824824
static mach_timebase_info_data_t timebase;
825-
static uint64_t t0 = 0;
826825
uint64_t ticks;
827826

828827
if (timebase.denom == 0) {
@@ -859,8 +858,6 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
859858
"mach_timebase_info is too large");
860859
return -1;
861860
}
862-
863-
t0 = mach_absolute_time();
864861
}
865862

866863
if (info) {
@@ -871,9 +868,6 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
871868
}
872869

873870
ticks = mach_absolute_time();
874-
/* Use a "time zero" to reduce precision loss when converting time
875-
to floatting point number, as in time.monotonic(). */
876-
ticks -= t0;
877871
*tp = _PyTime_MulDiv(ticks,
878872
(_PyTime_t)timebase.numer,
879873
(_PyTime_t)timebase.denom);
@@ -960,7 +954,6 @@ static int
960954
win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info)
961955
{
962956
static LONGLONG frequency = 0;
963-
static LONGLONG t0 = 0;
964957
LARGE_INTEGER now;
965958
LONGLONG ticksll;
966959
_PyTime_t ticks;
@@ -1000,7 +993,6 @@ win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info)
1000993
}
1001994

1002995
QueryPerformanceCounter(&now);
1003-
t0 = now.QuadPart;
1004996
}
1005997

1006998
if (info) {
@@ -1013,10 +1005,6 @@ win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info)
10131005
QueryPerformanceCounter(&now);
10141006
ticksll = now.QuadPart;
10151007

1016-
/* Use a "time zero" to reduce precision loss when converting time
1017-
to floatting point number, as in time.perf_counter(). */
1018-
ticksll -= t0;
1019-
10201008
/* Make sure that casting LONGLONG to _PyTime_t cannot overflow,
10211009
both types are signed */
10221010
Py_BUILD_ASSERT(sizeof(ticksll) <= sizeof(ticks));

0 commit comments

Comments
 (0)