Skip to content

fix(metrics): make clearance_p5_m reproducible - #15

Merged
HansRobo merged 1 commit into
tier4-mainfrom
fix/tdigest-p5-reproducibility
Aug 12, 2026
Merged

HansRobo merged 1 commit into
tier4-mainfrom
fix/tdigest-p5-reproducibility

Conversation

@HansRobo

@HansRobo HansRobo commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Original PR: tier4#339

Problem

clearance_p5_m does not reproduce between identical runs. tdigest.TDigest.compress()
re-inserts centroids in pyudorandom order from an unseeded global random. Building the same
digest from the same values five times in one process gives four distinct p5 values (relative
spread 2.7e-03).

Any A/B on this repository is affected: the field moves on its own.

Fix

Seed the RNG around digest construction.

Seeding alone is not sufficient — merged_percentile also depends on input order, because
t-digest merging is not associative. Both call sites already walk in sorted() order; a test
pins that.

getstate/seed/setstate is not re-entrant. Both call sites are on the main thread; the
invariant is documented.

Note

The reported percentile changes once. There is no loss of comparability: past values were not
comparable to each other either.

Tests

8 tests, all mutation-verified (removing the seeding, or the sorted(), fails them).

tdigest.TDigest.compress() re-inserts centroids in pyudorandom order from an unseeded global
random, so the same values give a different p5 every time -- four distinct values out of five
builds in one process, relative spread 2.7e-03. Any A/B on this repository is affected.

Seeding alone is not enough: merged_percentile also depends on input order, because t-digest
merging is not associative. Both call sites already walk in sorted() order and a test pins that.
getstate/seed/setstate is not re-entrant; both call sites are on the main thread and the invariant
is documented.

The reported percentile changes once. Past values were not comparable to each other either, so
nothing is lost. 8 tests, all mutation-verified.
@HansRobo
HansRobo requested a review from go-sakayori August 12, 2026 06:33
@HansRobo
HansRobo merged commit c0a2c30 into tier4-main Aug 12, 2026
@HansRobo
HansRobo deleted the fix/tdigest-p5-reproducibility branch August 12, 2026 06:48
HansRobo added a commit that referenced this pull request Aug 27, 2026
tdigest.TDigest.compress() re-inserts centroids in pyudorandom order from an unseeded global
random, so the same values give a different p5 every time -- four distinct values out of five
builds in one process, relative spread 2.7e-03. Any A/B on this repository is affected.

Seeding alone is not enough: merged_percentile also depends on input order, because t-digest
merging is not associative. Both call sites already walk in sorted() order and a test pins that.
getstate/seed/setstate is not re-entrant; both call sites are on the main thread and the invariant
is documented.

The reported percentile changes once. Past values were not comparable to each other either, so
nothing is lost. 8 tests, all mutation-verified.
HansRobo added a commit that referenced this pull request Aug 27, 2026
tdigest.TDigest.compress() re-inserts centroids in pyudorandom order from an unseeded global
random, so the same values give a different p5 every time -- four distinct values out of five
builds in one process, relative spread 2.7e-03. Any A/B on this repository is affected.

Seeding alone is not enough: merged_percentile also depends on input order, because t-digest
merging is not associative. Both call sites already walk in sorted() order and a test pins that.
getstate/seed/setstate is not re-entrant; both call sites are on the main thread and the invariant
is documented.

The reported percentile changes once. Past values were not comparable to each other either, so
nothing is lost. 8 tests, all mutation-verified.
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.

2 participants