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.
This commit is contained in:
parent
aa01011003
commit
3df5c68487
|
@ -166,6 +166,9 @@ Functions
|
||||||
Return the time of the specified clock *clk_id*. Refer to
|
Return the time of the specified clock *clk_id*. Refer to
|
||||||
:ref:`time-clock-id-constants` for a list of accepted values for *clk_id*.
|
:ref:`time-clock-id-constants` for a list of accepted values for *clk_id*.
|
||||||
|
|
||||||
|
Use :func:`clock_gettime_ns` to avoid the precision loss caused by the
|
||||||
|
:class:`float` type.
|
||||||
|
|
||||||
.. availability:: Unix.
|
.. availability:: Unix.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
@ -185,6 +188,9 @@ Functions
|
||||||
Set the time of the specified clock *clk_id*. Currently,
|
Set the time of the specified clock *clk_id*. Currently,
|
||||||
:data:`CLOCK_REALTIME` is the only accepted value for *clk_id*.
|
:data:`CLOCK_REALTIME` is the only accepted value for *clk_id*.
|
||||||
|
|
||||||
|
Use :func:`clock_settime_ns` to avoid the precision loss caused by the
|
||||||
|
:class:`float` type.
|
||||||
|
|
||||||
.. availability:: Unix.
|
.. availability:: Unix.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
@ -273,10 +279,17 @@ Functions
|
||||||
The reference point of the returned value is undefined, so that only the
|
The reference point of the returned value is undefined, so that only the
|
||||||
difference between the results of consecutive calls is valid.
|
difference between the results of consecutive calls is valid.
|
||||||
|
|
||||||
|
Use :func:`monotonic_ns` to avoid the precision loss caused by the
|
||||||
|
:class:`float` type.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
.. versionchanged:: 3.5
|
.. versionchanged:: 3.5
|
||||||
The function is now always available and always system-wide.
|
The function is now always available and always system-wide.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.10
|
||||||
|
On macOS, the function is now system-wide.
|
||||||
|
|
||||||
|
|
||||||
.. function:: monotonic_ns() -> int
|
.. function:: monotonic_ns() -> int
|
||||||
|
|
||||||
|
@ -295,8 +308,14 @@ Functions
|
||||||
point of the returned value is undefined, so that only the difference between
|
point of the returned value is undefined, so that only the difference between
|
||||||
the results of consecutive calls is valid.
|
the results of consecutive calls is valid.
|
||||||
|
|
||||||
|
Use :func:`perf_counter_ns` to avoid the precision loss caused by the
|
||||||
|
:class:`float` type.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. versionchanged:: 3.10
|
||||||
|
On Windows, the function is now system-wide.
|
||||||
|
|
||||||
.. function:: perf_counter_ns() -> int
|
.. function:: perf_counter_ns() -> int
|
||||||
|
|
||||||
Similar to :func:`perf_counter`, but return time as nanoseconds.
|
Similar to :func:`perf_counter`, but return time as nanoseconds.
|
||||||
|
@ -317,6 +336,9 @@ Functions
|
||||||
returned value is undefined, so that only the difference between the results
|
returned value is undefined, so that only the difference between the results
|
||||||
of consecutive calls is valid.
|
of consecutive calls is valid.
|
||||||
|
|
||||||
|
Use :func:`process_time_ns` to avoid the precision loss caused by the
|
||||||
|
:class:`float` type.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
.. function:: process_time_ns() -> int
|
.. function:: process_time_ns() -> int
|
||||||
|
@ -581,6 +603,17 @@ Functions
|
||||||
:class:`struct_time` object is returned, from which the components
|
:class:`struct_time` object is returned, from which the components
|
||||||
of the calendar date may be accessed as attributes.
|
of the calendar date may be accessed as attributes.
|
||||||
|
|
||||||
|
Use :func:`time_ns` to avoid the precision loss caused by the :class:`float`
|
||||||
|
type.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: time_ns() -> int
|
||||||
|
|
||||||
|
Similar to :func:`~time.time` but returns time as an integer number of nanoseconds
|
||||||
|
since the epoch_.
|
||||||
|
|
||||||
|
.. versionadded:: 3.7
|
||||||
|
|
||||||
|
|
||||||
.. function:: thread_time() -> float
|
.. function:: thread_time() -> float
|
||||||
|
|
||||||
|
@ -595,6 +628,9 @@ Functions
|
||||||
returned value is undefined, so that only the difference between the results
|
returned value is undefined, so that only the difference between the results
|
||||||
of consecutive calls in the same thread is valid.
|
of consecutive calls in the same thread is valid.
|
||||||
|
|
||||||
|
Use :func:`thread_time_ns` to avoid the precision loss caused by the
|
||||||
|
:class:`float` type.
|
||||||
|
|
||||||
.. availability:: Windows, Linux, Unix systems supporting
|
.. availability:: Windows, Linux, Unix systems supporting
|
||||||
``CLOCK_THREAD_CPUTIME_ID``.
|
``CLOCK_THREAD_CPUTIME_ID``.
|
||||||
|
|
||||||
|
@ -608,13 +644,6 @@ Functions
|
||||||
.. versionadded:: 3.7
|
.. versionadded:: 3.7
|
||||||
|
|
||||||
|
|
||||||
.. function:: time_ns() -> int
|
|
||||||
|
|
||||||
Similar to :func:`~time.time` but returns time as an integer number of nanoseconds
|
|
||||||
since the epoch_.
|
|
||||||
|
|
||||||
.. versionadded:: 3.7
|
|
||||||
|
|
||||||
.. function:: tzset()
|
.. function:: tzset()
|
||||||
|
|
||||||
Reset the time conversion rules used by the library routines. The environment
|
Reset the time conversion rules used by the library routines. The environment
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
:func:`time.perf_counter()` on Windows and :func:`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
|
||||||
|
:func:`time.perf_counter_ns()` and :func:`time.monotonic_ns()` added in Python
|
||||||
|
3.7 to avoid this precision loss.
|
|
@ -6,7 +6,7 @@
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */
|
#include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__has_builtin)
|
#if defined(__APPLE__) && defined(__has_builtin)
|
||||||
# if __has_builtin(__builtin_available)
|
# if __has_builtin(__builtin_available)
|
||||||
# define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
|
# define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
|
||||||
# endif
|
# endif
|
||||||
|
@ -730,7 +730,7 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
|
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -822,7 +822,6 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
|
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
static mach_timebase_info_data_t timebase;
|
static mach_timebase_info_data_t timebase;
|
||||||
static uint64_t t0 = 0;
|
|
||||||
uint64_t ticks;
|
uint64_t ticks;
|
||||||
|
|
||||||
if (timebase.denom == 0) {
|
if (timebase.denom == 0) {
|
||||||
|
@ -859,8 +858,6 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
"mach_timebase_info is too large");
|
"mach_timebase_info is too large");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
t0 = mach_absolute_time();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
|
@ -871,9 +868,6 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
}
|
}
|
||||||
|
|
||||||
ticks = mach_absolute_time();
|
ticks = mach_absolute_time();
|
||||||
/* Use a "time zero" to reduce precision loss when converting time
|
|
||||||
to floatting point number, as in time.monotonic(). */
|
|
||||||
ticks -= t0;
|
|
||||||
*tp = _PyTime_MulDiv(ticks,
|
*tp = _PyTime_MulDiv(ticks,
|
||||||
(_PyTime_t)timebase.numer,
|
(_PyTime_t)timebase.numer,
|
||||||
(_PyTime_t)timebase.denom);
|
(_PyTime_t)timebase.denom);
|
||||||
|
@ -960,7 +954,6 @@ static int
|
||||||
win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info)
|
win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
{
|
{
|
||||||
static LONGLONG frequency = 0;
|
static LONGLONG frequency = 0;
|
||||||
static LONGLONG t0 = 0;
|
|
||||||
LARGE_INTEGER now;
|
LARGE_INTEGER now;
|
||||||
LONGLONG ticksll;
|
LONGLONG ticksll;
|
||||||
_PyTime_t ticks;
|
_PyTime_t ticks;
|
||||||
|
@ -1000,7 +993,6 @@ win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryPerformanceCounter(&now);
|
QueryPerformanceCounter(&now);
|
||||||
t0 = now.QuadPart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
|
@ -1013,10 +1005,6 @@ win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
QueryPerformanceCounter(&now);
|
QueryPerformanceCounter(&now);
|
||||||
ticksll = now.QuadPart;
|
ticksll = now.QuadPart;
|
||||||
|
|
||||||
/* Use a "time zero" to reduce precision loss when converting time
|
|
||||||
to floatting point number, as in time.perf_counter(). */
|
|
||||||
ticksll -= t0;
|
|
||||||
|
|
||||||
/* Make sure that casting LONGLONG to _PyTime_t cannot overflow,
|
/* Make sure that casting LONGLONG to _PyTime_t cannot overflow,
|
||||||
both types are signed */
|
both types are signed */
|
||||||
Py_BUILD_ASSERT(sizeof(ticksll) <= sizeof(ticks));
|
Py_BUILD_ASSERT(sizeof(ticksll) <= sizeof(ticks));
|
||||||
|
|
Loading…
Reference in New Issue