GeezerVison is showing github.com — time.perf_counter() should state more clearly (or deny) that it is monotonic · Issue #115637 · python/cpython
time.perf_counter() should state more clearly (or deny) that it is monotonic #115637DescriptionDocumentation
I was trying to figure out the distinction between perf_counter and monotonic, and it's not entirely clear to me, even after reading PEP 418. I think it is monotonic, but I'm not sure.
So I'm invoking the Python gods here: what's the actual wanted behavior here? And why isn't it more clearly stated in the docs?
Thanks!
Linked PRs
Reacted by Alexandre Morignot, Alessio, Abbas Yadollahi, Artem, Charmander and NTFSvolume ActivityAlexWaygood commented on Feb 18, 2024 @vstinner, I think you might be the expert here? :) anarcat commented on Feb 18, 2024 alright, i guess #115638 should fix the docs then. :) gaogaotiantian commented on Feb 18, 2024 From my personal opinion, the fact that it is currently monotonic, does not mean that we should document it and make a promise about it. We already promised one thing about perf_counter() - it'll be the most precise timer on the system. If we make another promise that this'll be monotonic, then what happens if a system comes up with the most precise timer not being monotonic? We can't keep both promises anymore. That's probably just a imaginary scenario and one may argue that all the platforms we support at this time have the most precise timers as monotonic, which might be the real case at least for now. vstinner commented on Feb 19, 2024 I'm not 100% sure that perf_counter() is always monotonic in all cases on all platforms. It would help to have some evidence on Linux, Windows, macOS. vstinner commented on Feb 19, 2024 See also #88494
On Windows, QueryPerformanceCounter() is implemented by reading x86 TSC. Ten years ago, TSC causes issues when the CPU frequency changed: recent CPU now have a TSC which is no longer related to the CPU frequency. There were also a few issues related to virtualization.
Today, Windows documentation just says: https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps
Is the performance counter monotonic (non-decreasing)?
Yes. QPC does not go backward.
where QPC stands for QueryPerformanceCounter().
Linux supports multiple clock sources and can switch to the next one at runtime if Linux decides that a clock is not reliable. Example on my laptop:
$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
tsc
$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc acpi_pm
TSC and ACPI PM are available and TSC is the current clock source. vstinner commented on Feb 19, 2024 PyTime_PerfCounter() has these implementations:
- Windows: QueryPerformanceCounter() -- monotonic
- macOS: mach_absolute_time() -- monotonic
- HP-UX: gethrtime() -- monotonic
- clock_gettime(CLOCK_HIGHRES) -- monotonic
- clock_gettime(CLOCK_MONOTONIC) -- monotonic
Oh, in fact, Python time.get_clock_info('perf_counter') announces monotonic=True on all platforms! Example on Linux:
$ python3.13
Python 3.13.0a3 (main, Jan 18 2024, 00:00:00) [GCC 13.2.1 20231205 (Red Hat 13.2.1-6)] on linux
>>> import time
>>> time.get_clock_info('perf_counter')
namespace(implementation='clock_gettime(CLOCK_MONOTONIC)', monotonic=True, adjustable=False, resolution=1e-09)
anarcat commented on Feb 19, 2024 from what i can tell in the Fine Source Code:
|
int |
|
_PyTime_GetPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info) |
|
{ |
|
#ifdef MS_WINDOWS |
|
return py_get_win_perf_counter(t, info, 1); |
|
#else |
|
return _PyTime_GetMonotonicClockWithInfo(t, info); |
|
#endif |
|
} |
it does look like on everything but MS_WINDOWS, it defers to _PyTime_GetMonotonicClockWithInfo, so it's not only monotonic, it's exactly like time.monotonic().
But those are implementation details: i think the fundamental question here is whether or not the plan was to have the performance counter be monotonic in the first place, or, if that's the requirement anyway.
Looking at it from a library consumer perspective, i'm looking at the codetiming package and it's implemented with perf_counter. it's exactly the kind of module I would expect perf_counter to be used for, but I would also be extremely surprised if the counter would go backwards on time shifts, for example.
So I would personnally argue that perf_counter() is a superset of monotonic(). But I would understand if it would make things more complicated for implementers and if it wasn't the original intention of PEP418. But then I really wonder how one would be supposed to implement codetiming then: should it avoid using perf_counter() because it could eventually go backwards? or should it use both perf_counter() and monotonic and fallback on the latter if the former goes backwards? iffy... Reacted by Thomas B. Brunner, Alexandre Morignot, Kasisnu, Árpád Goretity and NTFSvolume StanFromIreland commented on Jun 5, 2026 Closing, this was documented in 846ad5a.
MetadataMetadataStatusShow more project fields
DevelopmentNo branches or pull requestsIssue actions
|