Skip to content

Calibrate TSC frequency instead of scraping /proc/cpuinfo#392

Open
bushidocodes wants to merge 1 commit into
masterfrom
fix/cpu-speed-tsc-calibration
Open

Calibrate TSC frequency instead of scraping /proc/cpuinfo#392
bushidocodes wants to merge 1 commit into
masterfrom
fix/cpu-speed-tsc-calibration

Conversation

@bushidocodes

Copy link
Copy Markdown
Contributor

Summary

The runtime times everything with __getcycles()rdtsc, the invariant TSC, which ticks at a fixed rate regardless of the core's current p-state. But runtime_get_processor_speed_MHz() derived its cycles↔microseconds conversion factor by scraping the instantaneous cpu MHz from /proc/cpuinfo, which reports the core's current operating frequency. That value varies under frequency scaling / TurboBoost (and shows natural per-read variance on recent Intel parts even under the performance governor), so the factor was both wrong (it is not the TSC rate) and unstable across startups — corrupting deadline math. The prior workaround was hardcoding a value via SLEDGE_PROC_MHZ.

Fix

Calibrate the TSC rate directly: count rdtsc cycles over timed CLOCK_MONOTONIC_RAW windows (5 × 20 ms) and take the maximum rate. A deschedule during a window only ever stretches the measured wall time (lowering the apparent rate), so the max rejects that noise. This measures the actual TSC frequency and is stable regardless of governor/p-state. The SLEDGE_PROC_MHZ override is preserved.

Single-file change (runtime/src/main.c).

Verification

Built and run in the Docker dev environment:

  • Accurate — calibrates 3793 MHz; an independent 1-second rdtsc measurement reads 3792.9 MHz (~0.003% error).
  • Stable — 3793 MHz across 6/6 restarts.
  • Override worksSLEDGE_PROC_MHZ=2100 reports 2100 MHz.
  • Functional — a resize request returns output byte-identical to the test's expected result (timing/deadlines intact).

Closes #246.

🤖 Generated with Claude Code

The runtime times everything with __getcycles() (rdtsc), the invariant
TSC, which ticks at a fixed rate independent of the core's current
p-state. But runtime_get_processor_speed_MHz() derived its cycles<->us
conversion factor from the instantaneous "cpu MHz" in /proc/cpuinfo,
which reports the core's current operating frequency. That value varies
under frequency scaling and TurboBoost (and exhibits natural per-read
variance on recent Intel parts even under the performance governor), so
the conversion factor was both wrong (it is not the TSC rate) and
unstable across startups, corrupting deadline math. The previous
workaround was hardcoding a value via SLEDGE_PROC_MHZ.

Calibrate the TSC rate directly instead: count rdtsc cycles over timed
CLOCK_MONOTONIC_RAW windows (5 x 20 ms) and take the maximum rate. A
deschedule during a window only ever stretches the measured wall time,
lowering the apparent rate, so the max rejects that noise. This measures
the actual TSC frequency and is stable regardless of governor/p-state.
The SLEDGE_PROC_MHZ override is preserved.

Verified: calibrates 3793 MHz, stable across 6 restarts, matching an
independent 1-second rdtsc measurement (3792.9 MHz); override and
end-to-end request serving both work.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runtime reports varying processor speed at startup

1 participant