Repository navigation
perf(tdigest): reuse cumulative weights in CDF and PMF queries - #289
Merged
Merged
Conversation
When the combined weight of collected inputs is at most k / 2, no two centroids fit under the K_2 limit, so the k-way heap merge only reproduces the stable-sorted concatenation one centroid at a time. Take the same sort path as mixed compressed/buffered inputs, which already skips the merge scan at these counts.
cdf and pmf answered each split point with an independent rank query, rescanning the centroid weights twice per point. Precompute each centroid's starting weight once; integer prefix differences are exact, so results are bit-identical while each point costs two binary searches.
The view layer already returns None for empty centroid sequences, and compressing an empty buffer is a no-op, so the early returns in TDigestMut::cdf, pmf, quantile, and quantiles only duplicated the view contract. TDigestMut::rank keeps its check: the empty digest's sentinel extrema would otherwise answer out-of-range queries instead of None.
The COMPAT_DOUBLE and COMPAT_FLOAT arms ran the same validation pipeline with only scalar widths, the capacities field, and message labels differing. Parameterize them behind CompatLayout, keeping every error message byte-identical.
Shapes with a combined weight of at most k / 2 exercise the no-merge fast paths in both borrowed and collected merging. Also document the faster multi-point cdf and pmf in the changelog.
Reuse the weight below the previous anchor instead of allocating a full prefix array for every CDF call. Sorted split points make the lower anchors monotonic, so each query only sums the newly crossed weights. Keep the existing rank interpolation shared with scalar queries and scope the changelog claim to queries with many split points.
Restore the separate double and float decoding paths. The shared CompatLayout reader adds calls to each centroid iteration and regresses throughput; keeping the existing loops also removes the layout helpers. Validation rules, conversion order, and error messages stay unchanged.
Add k=440 to the existing 220-weight interleaved-input fixture and remove the duplicate small-input test. This covers the exact k/2 boundary while retaining weighted ties, both compression directions, and later updates.
A combined weight below k / 2 proves that no centroids can merge, but sorting the concatenated inputs is not consistently cheaper than merging their existing sorted runs. Restore the original routing after the sort path regressed two compressed 50-row inputs by about 11%. Remove the benchmark shapes and test parameter added for that routing. The existing interleaved, mixed-input, and weighted collection tests remain unchanged from main. Validation: cargo test --package tests-integration --test tdigest_test (52 tests passed).
Return None from cdf, pmf, quantile, and quantiles before entering the compression and view path for an empty digest. The view-level checks remain necessary for frozen queries but do not make these early returns redundant for performance. Keep argument validation before the early returns, preserving the existing panic contracts even when the digest is empty. Validation: cargo x check, cargo x test (745 tests), and cargo x lint.
tisonkun
enabled auto-merge (squash)
October 5, 2026 00:22
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cdfandpmfpreviously recomputed cumulative centroid weights from the beginning for each split point. They now accumulate integer weights as sorted split points advance, sharing scalar rank's anchors and interpolation without allocating a prefix array.The final diff contains only the query implementation and its changelog entry. Collection routing, empty-digest fast returns, compatibility decoders, existing tests, public signatures, and serialization layouts match the base branch.
Performance
Temporary library-level probes on Apple ARM64 with release builds, using the median of three interleaved runs against base
e7f1b9f. The final implementation is9b1bb86; the digests usek = 200and 100,000 input values.CDF allocates only its result vector. These are workload-specific microbenchmarks, not an application-wide performance claim.
Validation
cargo x check,cargo x test(745 tests), andcargo x lintpass on the final implementation.