-
-
Notifications
You must be signed in to change notification settings - Fork 348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Figure out if we're using the correct clocks everywhere #1586
Comments
Now that my world has been shaken a bit, I feel like we should also double-check that I'm right that the |
@vstinner BTW, if you check out this issue it documents some quirks in how |
You should dig into https://www.python.org/dev/peps/pep-0418/ and search for "suspend". Handling time is hard :-) |
@vstinner Ha, you don't have to tell me :-) It does look like this statement from PEP 418 may not be true anymore:
In particular, all supported Windows versions now have both clocks available, but Python only wraps the keeps-ticking-during-suspend version. (Hmm, I guess this is actually a bug in asyncio as well, since they also want a clock that stops ticking during suspend...) |
GetTickCount64 is the right one for Windows. |
@FastInvite2k2 we switched away from using that a few years ago – see #33 for discussion |
Also, aside from the resolution issues we ran into in #33, from the docs it looks like |
Trio's standard clock is intended to be a monotonic clock that ticks only while the system is running, not while it's suspended. (Rationale: this is the kind of clock that blocking primitives like epoll/
GetQueuedCompletionEvents
/kqueue use for theirtimeout
parameter, and we want times on the Trio clock to be convertable intotimeout
s for these calls.)Is this true? Currently we use
time.perf_counter()
for our clock.Linux
We're ok:
time.perf_counter()
eventually callsclock_gettime(CLOCK_MONOTONIC, ...)
, and on Linux,CLOCK_MONOTONIC
has the properties mentioned above.macOS
We're ok:
time.perf_counter()
eventually callsmach_absolute_time()
, whose docs say:(Note: on macOS,
clock_gettime(CLOCK_MONOTONIC, ...)
does not work like this – it keeps ticking while the system is suspended. So it's good that Python's time module doesn't use this!)FreeBSD
I'm pretty sure we do the wrong thing:
time.perf_counter()
eventually ends up onpymonotonic
, which ends up usingCLOCK_MONOTONIC
, and on FreeBSD this does keep ticking during suspend: https://www.freebsd.org/cgi/man.cgi?query=clock_gettimeInstead, we should use
clock_gettime(CLOCK_UPTIME, ...)
.(Also, perhaps, file a bug on Python? Not sure what the contract for
time.monotonic()
/time.perf_counter()
is supposed to be.)Windows
I'm pretty sure we do the wrong thing:
time.perf_counter()
callsQueryPerformanceCounter
, and the docs say:...It is super unclear what you are supposed to do instead.
[pause to scrounge around weird corners of the internet]
OK so it sounds like the official options are:
QueryUnbiasedInterruptTime
– but this is relatively low resolution, usually the same 15 ms resolution that we originally switched toQueryPerformanceCounter
to avoid, see Which clock should we use on Windows? #33QueryUnbiasedInterruptTimePrecise
– exactly what we want, but the docs imply that it might be kinda slow. We should measure to find out if that's actually true.Use
QueryPerformanceCounter
(which includes time spend suspended) plus some eldritch magic to figure out how long the system has spent suspended, so we can subtract it off again to "correct" theQueryPerformanceCounter
output. Specifically, user-space processes can apparently find the number of 100 ns ticks that the system has spent suspended stored as an unsigned 64-bit value at memory address 0x7ffe03b0.I swear I'm not making this up.
The text was updated successfully, but these errors were encountered: