python-trio / python-trio/trio

Figure out if we're using the correct clocks everywhere

Open
#1,586 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

low-level
Dominant language
Python
Stars
7.3k
Forks
431
Avg merge
2d 17h
Merged PRs (30d)
6

Description

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 their timeout parameter, and we want times on the Trio clock to be convertable into timeouts for these calls.)

Is this true? Currently we use time.perf_counter() for our clock.

Linux

We're ok: time.perf_counter() eventually calls clock_gettime(CLOCK_MONOTONIC, ...), and on Linux, CLOCK_MONOTONIC has the properties mentioned above.

macOS

We're ok: time.perf_counter() eventually calls mach_absolute_time(), whose docs say:

Returns current value of a clock that increments monotonically in tick units (starting at an arbitrary point), this clock does not increment while the system is asleep.

(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 on pymonotonic, which ends up using CLOCK_MONOTONIC, and on FreeBSD this does keep ticking during suspend: https://www.freebsd.org/cgi/man.cgi?query=clock_gettime

Instead, 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() calls QueryPerformanceCounter, and the docs say:

QueryPerformanceCounter reads the performance counter and returns the total number of ticks that have occurred since the Windows operating system was started, including the time when the machine was in a sleep state such as standby, hibernate, or connected standby.

...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:

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating Trio's standard-clock implementation and every use of time.perf_counter(), then compare the Linux, macOS, FreeBSD, and Windows behavior described in the issue. Measure QueryUnbiasedInterruptTimePrecise against the alternatives on Windows and define done as selecting and validating a monotonic, suspend-excluding clock strategy for each platform.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.