Skip to content

feat: add instrument_hooks_monotonic_offset - #35

Closed
lvaroqui wants to merge 1 commit into
mainfrom
feat/monotonic-offset
Closed

lvaroqui wants to merge 1 commit into
mainfrom
feat/monotonic-offset

Conversation

@lvaroqui

Copy link
Copy Markdown
Contributor

Add instrument_hooks_monotonic_offset(), the offset in nanoseconds to add to instrument_hooks_current_timestamp() to read it as a wall clock time since the Unix epoch. It returns 0 where the monotonic clock is unavailable (Windows).

Integrations exporting OpenTelemetry spans and logs timestamp them with the same monotonic clock as the benchmark markers, shifted by this offset so they still read as wall clock times in standard tools. Subtracting the offset gives back the exact marker clock. For that to hold, every exporter in a process has to use the same offset, so it is computed on the first call and cached for the process instead of each integration computing its own. Two separately computed offsets differed by ~400 ns in practice.

The header also defines INSTRUMENT_HOOKS_MONOTONIC_OFFSET_ATTRIBUTE ("codspeed.clock.monotonic_offset_ns"), the OpenTelemetry resource attribute carrying the offset, so the name lives in one place.

The offset pairs one realtime clock read with the midpoint of two monotonic reads. Wall clock adjustments after the first call make shifted timestamps drift from the wall clock (by milliseconds at most over a benchmark run), but the monotonic value recovered by subtracting stays exact.

Notes for review:

  • dist/core.c is regenerated with Zig 0.14.0. Neither 0.14.0 nor 0.14.1 reproduces the current file byte-for-byte here (symbol numbering is shifted), and 0.14.0 gives the smaller diff; it is mostly renumbered transpiler symbols.
  • The per-span conversion of SDK wall clock times stays in each integration, since it depends on which clock the language's OpenTelemetry SDK reads.

Refs COD-3862: the issue stays open for the integration side using this offset.

Integrations exporting OpenTelemetry spans and logs timestamp them with the
monotonic clock of the benchmark markers, shifted to read as wall clock
times. Each computing its own offset would shift timestamps differently
within a process, so subtracting one offset would no longer give back the
exact monotonic timestamp.

Expose the offset from `instrument_hooks_current_timestamp` to the wall
clock as `instrument_hooks_monotonic_offset`, computed on the first call
and cached for the process, or 0 where the monotonic clock is unavailable.

The runner places that telemetry on the clock of the benchmark markers,
so it needs the offset too: in analysis mode, the hooks send it in a new
`SetTelemetryMonotonicOffset { pid, offset_ns }` command once the
integration mode is negotiated. This bumps the protocol to version 3.

Refs COD-3862
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lvaroqui
lvaroqui force-pushed the feat/monotonic-offset branch from 6bb632a to f1b1207 Compare October 20, 2026 14:33
@lvaroqui

Copy link
Copy Markdown
Contributor Author

Dropped: integrations now record the time of their spans and logs on the monotonic clock of the benchmark markers as attributes, so the hooks no longer need to share a monotonic-to-wall-clock offset with the runner.

@lvaroqui lvaroqui closed this Oct 23, 2026
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.

1 participant