Skip to content

feat: expose detected timer resolution per task#570

Closed
jerome-benoit wants to merge 1 commit into
tinylibs:mainfrom
jerome-benoit:feat/detected-resolution-diagnostic
Closed

feat: expose detected timer resolution per task#570
jerome-benoit wants to merge 1 commit into
tinylibs:mainfrom
jerome-benoit:feat/detected-resolution-diagnostic

Conversation

@jerome-benoit

Copy link
Copy Markdown
Collaborator

Summary

Add a Task.detectedResolution getter (number | undefined) populated after each run with the smallest strictly positive latency sample observed. A new estimateResolution helper is exported from src/utils.ts and from the public entry point.

const bench = new Bench()
bench.add('hot fn', () => regex.test(line))
await bench.run()

const task = bench.getTask('hot fn')
console.log(task?.detectedResolution) // ms, or undefined

Semantics

task.detectedResolution is:

  • undefined before the first successful run
  • undefined when all samples of the last run were zero (timer too coarse to resolve any iteration)
  • undefined after task.reset()
  • otherwise the smallest strictly positive sample, in milliseconds

The smallest non-zero sample is a conservative upper bound on the effective timer resolution: a timer of resolution R cannot return a non-zero delta smaller than R. It is more reliable than a nominal value carried by the TimestampProvider because it observes the actual resolution at the moment of measurement (subject to OS scheduler jitter, power-saving modes, etc.).

Implementation

estimateResolution is a single linear scan; the cost is negligible relative to a benchmark run. The diagnostic is always populated — no new option, no opt-in. Useful for users who want to interpret latency.mean honestly for sub-µs functions, or to feed downstream guards (e.g. a CI that fails when detectedResolution > X due to a degraded environment).

Risk

None — purely additive: new public getter on Task, new export in the entry point. No change to existing options, types, or measurement behavior.

Add a Task.detectedResolution getter (number | undefined) populated after
each run with the smallest strictly positive latency sample observed. It
is undefined before the first successful run, when all samples are zero
(timer too coarse to resolve any iteration), or after Task#reset().

A new estimateResolution helper is exported from src/utils.ts and from
the public entry point. The implementation is purely additive:
no new option, no behavior change for existing benchmarks.
@jerome-benoit jerome-benoit requested a review from Uzlopak as a code owner May 30, 2026 00:35
@pkg-pr-new

pkg-pr-new Bot commented May 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/tinylibs/tinybench@570

commit: 2031a7a

@jerome-benoit

Copy link
Copy Markdown
Collaborator Author

Closed in favor of #571 which consolidates this feature with #568 and #569. The audit found that estimateResolution must operate on the raw latency samples; running it after the in-place overhead correction from #568 returns either a value shifted down by the calibrated overhead or undefined when every sample is clamped to zero, in both cases breaking the diagnostic. The consolidated PR also replaces the strict-minimum estimator (breakdown 1/n — a single outlier sample tilts the result) with the smallest strictly-positive value that appears at least twice (breakdown 2/n), with a fall-back to the strict minimum when no value repeats.

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