Skip to content

feat(tick): add configurable fast instant retrieval - #648

Merged
martintmk merged 25 commits into
mainfrom
user/martintomka/20260806-add-fast-instant-tick
Aug 13, 2026
Merged

martintmk merged 25 commits into
mainfrom
user/martintomka/20260806-add-fast-instant-tick

Conversation

@martintmk

@martintmk martintmk commented Aug 6, 2026 •

Copy link
Copy Markdown
Member

Adds an optional per-clock fast instant source behind the fast-instant feature without changing default behavior. Clock::with_fast_instant(self, enabled) and SimpleClock::with_fast_instant(self, enabled) configure the existing instant() path. This lets callers keep a precise clock and create an independently configured fast clone; stopwatches created from each clone inherit its source. Timer scheduling remains on the clock driver's precise time source so Delay and PeriodicTimer cannot miss a wake when coarse retrieval lags. Controlled clocks are unaffected. On Linux, fast retrieval uses CLOCK_MONOTONIC_COARSE; on Windows, it uses GetTickCount64; other targets delegate to std::time::Instant::now(). Fast retrieval uses one process-wide calibration, keeping values comparable across threads without per-clock state, thread-local state, or caching. The implementation is private to tick and uses only target-specific optional FFI dependencies. The Criterion benchmark compares the public precise and configured-fast paths. A current Windows run measured approximately 29.75 ns for precise retrieval and 4.74 ns for fast retrieval, about 6.3x faster. Validation: tick all-feature and feature-disabled tests, all-feature doctests, Clippy with warnings denied, pinned Miri, formatting, generated README, and spelling pass. cargo package remains blocked by the existing published thread_aware 0.8.0 feature mismatch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
@martintmk martintmk added the agency-rocket Touched by a rocket skill label Aug 6, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Comment thread crates/tick/src/simple_clock.rs Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Comment thread crates/tick/src/fast_instant.rs Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Comment thread crates/tick/Cargo.toml
Comment thread crates/tick/src/clock.rs Outdated
Comment thread crates/tick/benches/tick_instant.rs Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
@martintmk martintmk changed the title feat(tick): add fast instant APIs feat(tick): add configurable fast instant retrieval Aug 6, 2026
@martintmk
martintmk marked this pull request as ready for review August 6, 2026 18:07
Copilot AI lite review requested due to automatic review settings August 6, 2026 18:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@codecov

codecov Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.0%. Comparing base (3661f6f) to head (9b92141).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #648   +/-   ##
=======================================
  Coverage   100.0%   100.0%           
=======================================
  Files         473      474    +1     
  Lines       45913    45963   +50     
=======================================
+ Hits        45913    45963   +50     
Flag Coverage Δ
linux 82.9% <100.0%> (-17.1%) ⬇️
linux-arm 82.4% <100.0%> (-17.6%) ⬇️
scheduled ?
windows 84.0% <100.0%> (-16.0%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Copilot AI review requested due to automatic review settings August 7, 2026 05:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (3)

crates/tick/src/simple_clock.rs:49

  • SystemFast is documented as reading lower-precision OS time, but the implementation only changes the Instant source (while system_time() still uses SystemTime::now()). Updating the variant doc comment will avoid misleading readers about what becomes lower precision.
    /// Reads lower-precision OS time with lower overhead.
    #[cfg(feature = "fast-instant")]
    SystemFast,

crates/tick/src/fast_instant.rs:64

  • platform_time() unconditionally panics if clock_gettime(CLOCK_MONOTONIC_COARSE) fails. That can bring down production code when fast-instant is enabled on older/atypical Linux environments where _COARSE is unavailable. Consider falling back to CLOCK_MONOTONIC before panicking.
    let result = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, timestamp.as_mut_ptr()) };
    assert_eq!(
        result,
        0,
        "CLOCK_MONOTONIC_COARSE must be available: {}",

crates/tick/src/fast_instant.rs:125

  • platform_time_is_nonzero can be flaky on freshly booted systems (both CLOCK_MONOTONIC_COARSE and GetTickCount64 can legitimately return 0 near boot). A monotonic/non-decreasing assertion avoids this unnecessary failure mode.
    #[test]
    fn platform_time_is_nonzero() {
        assert_ne!(platform_time(), Duration::ZERO);
    }

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Copilot AI review requested due to automatic review settings August 7, 2026 06:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (2)

crates/tick/src/fast_instant.rs:108

  • repeated_calls_use_cached_instant is likely to be flaky: it assumes the coarse platform clock will return identical consecutive timestamps within 1,000 iterations, which is not guaranteed (e.g., if the platform clock resolution is 1ms and the loop body takes >1ms per iteration). This can cause spurious CI failures while not asserting a stable correctness property.

Consider rewriting this as a deterministic monotonicity check (or removing the test if caching is purely an optimization).

        for _ in 0..1_000 {
            let current = now();
            if current == previous {
                return;
            }

crates/tick/src/fast_instant.rs:122

  • platform_time_is_nonzero assumes the platform monotonic clock cannot return Duration::ZERO, but 0 is a valid monotonic timestamp (e.g., right after boot). This makes the test encode an unnecessary and potentially flaky constraint.

A better invariant to assert is monotonicity (second call >= first).

    #[test]
    fn platform_time_is_nonzero() {
        assert_ne!(platform_time(), Duration::ZERO);
    }

Comment thread crates/tick/src/clock.rs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Regenerate the tick README to resolve the generated-file conflict.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Copilot AI review requested due to automatic review settings August 10, 2026 14:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (2)

crates/tick/src/fast_instant.rs:120

  • Same here: prefer .unwrap() over .expect(...) when joining a spawned test thread.
        let second = std::thread::spawn(move || calibration.now_at(calibration.platform_epoch + Duration::from_millis(2)))
            .join()
            .expect("test thread must complete");

crates/tick/src/fast_instant.rs:117

  • In test code we generally prefer .unwrap() over .expect(...) for JoinHandle::join(). The panic backtrace already points at the failing thread join, and this keeps test style consistent across the repo.

This issue also appears on line 118 of the same file.

        let first = std::thread::spawn(move || calibration.now_at(calibration.platform_epoch + Duration::from_millis(1)))
            .join()
            .expect("test thread must complete");

Copilot AI review requested due to automatic review settings August 12, 2026 10:56
@martintmk
martintmk enabled auto-merge (squash) August 12, 2026 10:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (1)

crates/tick/src/fast_instant.rs:40

  • The checked_add(...).expect("a monotonic platform timestamp cannot exceed the range of Instant") message is not a valid justification: monotonicity does not imply the value is within Instant’s representable range. If this is intended to be an impossible condition, the expect message should explain the real invariant (e.g., that elapsed is bounded by process uptime / platform counter range, so overflow would require implausibly long uptime).
            .expect("a monotonic platform timestamp cannot exceed the range of Instant")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Copilot speaking]

Published 2 findings. One finding follows up on an existing discussion thread.

See diagnostics
Diagnostic Value
Cache Hit

Comment thread crates/tick/src/fast_instant.rs Outdated
Comment thread crates/tick/src/clock.rs Outdated
Remove the unsubstantiated same-crate inline hint from the fast instant helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Preserve the independently merged main changes before pushing review fixes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Copilot AI review requested due to automatic review settings August 12, 2026 12:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (1)

crates/tick/src/fast_instant.rs:56

  • clock_gettime(CLOCK_MONOTONIC_COARSE, ...) can fail for reasons other than the clock ID not existing (e.g., sandbox/seccomp restrictions). Panicking here turns an optional performance feature into a process-aborting reliability risk. Consider handling a non-zero return by falling back to Instant::now() for that call (or disabling the fast path after a failed calibration) instead of asserting.
    let result = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, timestamp.as_mut_ptr()) };
    assert_eq!(result, 0, "CLOCK_MONOTONIC_COARSE predates Rust's minimum supported Linux kernel");

Comment thread crates/tick/src/periodic_timer.rs Outdated
Follow the crate's any(feature, test) gating convention and provide target-specific dev dependencies for the platform clocks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Copilot AI review requested due to automatic review settings August 12, 2026 13:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (2)

crates/tick/src/fast_instant.rs:56

  • platform_time() panics the entire process if clock_gettime(CLOCK_MONOTONIC_COARSE, ...) fails (e.g., due to seccomp/sandboxing). Since this is an optional performance feature, it’s safer to fall back to a more widely supported monotonic clock rather than crashing.
    let result = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, timestamp.as_mut_ptr()) };
    assert_eq!(result, 0, "CLOCK_MONOTONIC_COARSE predates Rust's minimum supported Linux kernel");

crates/tick/src/periodic_timer.rs:210

  • This test only asserts that timer.next() completes before the timeout, but it would also pass if the stream unexpectedly returned None. Since PeriodicTimer is documented to never complete, the test should assert the item is Some(()) to avoid masking regressions.
        tokio::time::timeout(Duration::from_secs(1), timer.next())
            .await
            .expect("timer scheduling uses the driver's precise time source");
    }

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f6987d90-a184-4cb2-8d5a-99581cb6d507
Copilot AI review requested due to automatic review settings August 12, 2026 13:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (1)

crates/tick/src/fast_instant.rs:56

  • The panic message on clock_gettime failure is misleading: clock_gettime(CLOCK_MONOTONIC_COARSE, ...) can fail for reasons other than an unsupported kernel (e.g., sandboxing/seccomp or unexpected OS errors), so the current message could send debugging in the wrong direction. Consider using an error message that reflects the actual call that failed and the expected invariant.
    assert_eq!(result, 0, "CLOCK_MONOTONIC_COARSE predates Rust's minimum supported Linux kernel");

@martintmk
martintmk merged commit da3dd8f into main Aug 13, 2026
52 checks passed
@martintmk
martintmk deleted the user/martintomka/20260806-add-fast-instant-tick branch August 13, 2026 05:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agency-rocket Touched by a rocket skill

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants