Skip to content

Define the time filter algorithm in the spec - #303

Open
maximmaxim345 wants to merge 8 commits into
mainfrom
docs/embed-time-filter
Open

maximmaxim345 wants to merge 8 commits into
mainfrom
docs/embed-time-filter

Conversation

@maximmaxim345

@maximmaxim345 maximmaxim345 commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Moves the time filter algorithm from the time-filter repository into Clock Synchronization, so the spec defines it directly instead of only linking to it.

The algorithm itself stays a MUST, like before. The parameter values are now a SHOULD, where before they were only the library's defaults. The burst strategy from the library README is now a MUST instead of a known-good baseline, with at least 8 messages per burst and at most 10 s between burst starts. Servers must not close the connection only because bursts are late, since a network stall can delay them.

The filter now ignores samples with a max_error of 0 or less, the same as the reference implementation:

I dropped the aiosendspin link since it doesn't follow the burst pattern.

Open question: Should the parameter values be a MUST?

The player sync accuracy floor is measured against the client's own filter, not the server clock, so a badly tuned filter can be compliant but out of sync. This PR makes the values a SHOULD, but I'm not sure that's the right level.

MUST:

  • Closes that gap, and every client syncs the same way.
  • Adaptive forgetting only starts after about 17 minutes at one burst per 10 s.
  • The time-filter README calls the values preliminary, and sendspin-js and sendspin-rs use other values today.

SHOULD (this PR):

  • Gives implementations one known-good default, while still allowing tuned values.
  • Leaves the gap open.

No keyword, like before:

  • Describes the reference without asking implementations to follow it.
  • Leaves the gap open.

Implementations

Only sendspin-cpp matches the reference everywhere:

Implementation Algorithm (MUST) Parameters (SHOULD) Bursts (MUST) Integer inputs (MUST) Rounding (MUST)
sendspin-cpp yes yes yes yes yes
sendspin-dotnet no, waits 5 measurements before using drift and adds minimum variances yes yes, every 500 ms until converged, then every 10 s no, floating point no, halves to even
SendspinDroid no, adds outlier rejection and a ±500 ppm drift limit yes no, 3 to 15 messages 50 ms apart without waiting for replies, every 0.2 to 3 s yes, plus a 1 µs minimum for max_error no, halves toward positive infinity
aiosendspin no, adds a minimum for S yes no, single messages every 0.2 to 3 s, every sample fed no, rounds halves to even no, halves to even
sendspin-js yes no no, feeds the median of the 3 lowest-delay samples no, floating point no, halves toward positive infinity
sendspin-rs no, no drift from samples under 100 ms apart, >= in the drift test, conversions refused above 0.2 drift no no, single messages every 1 s, every sample fed no, measurement rounds halves away from zero yes

sendspin-js uses process_std_dev 0.01, forget_factor 1.1, drift_process_std_dev 0, adaptive_cutoff 2.0 and no max_error_scale. sendspin-rs uses process_std_dev 0.01, forget_factor 1.001, drift_process_std_dev 0, adaptive_cutoff 0.75 and no max_error_scale.

Closes #293

Comment thread README.md Outdated
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.

Include time filter into the specification

2 participants