Skip to content

perf: sort the push buffer by integer keys - #5

Open
kei-nan wants to merge 1 commit into
MnO2:masterfrom
kei-nan:perf-integer-key-flush-sort
Open

kei-nan wants to merge 1 commit into
MnO2:masterfrom
kei-nan:perf-integer-key-flush-sort

Conversation

@kei-nan

@kei-nan kei-nan commented Oct 13, 2026

Copy link
Copy Markdown

flush sorts the pending buffer with f64::total_cmp, which applies its bit transform to both operands on every comparison. This PR stores pending values as total-order u64 keys instead. The transform runs once per value in push, and the sort compares plain integers.

  • compress_sorted now takes an ExactSizeIterator<Item = f64>, so flush decodes keys while compressing, with no scratch allocation. merge_sorted passes iter().copied().
  • The mean() overflow fallback decodes buffered keys the same way.
  • No public API change. The order is exactly total_cmp's, so flushed centroids are unchanged.

Tests

  • test_total_order_key_matches_total_cmp: key order matches total_cmp across signed zeros, subnormals and extremes, and keys round-trip bit-exactly.
  • buffered_flush_matches_batch_merges (proptest): push + flush gives the same centroids as chunked merge_unsorted. I checked that this test fails if the sort is removed.

The existing buffered_flush and incremental_ingest/buffered_push benches cover this path. I haven't included timings from a quiet machine, so please run those benches to judge the gain.

Checked locally: cargo test (debug and release, all feature sets), clippy -D warnings, rustdoc -D warnings, no_std, and the MSRV 1.62 checks from CI.

One side effect: Debug output for a digest with pending values shows the internal keys rather than f64s.

🤖 Generated with Claude Code

flush sorted the pending buffer with f64::total_cmp, which applies its
bit transform to both operands on every comparison. Store pending
values as total-order u64 keys instead, transformed once in push, so
the sort compares plain integers. compress_sorted now takes an
iterator, letting flush decode keys as it compresses without a scratch
allocation.

The order is exactly total_cmp's, so flushed centroids are unchanged; a
property test checks buffered ingestion against chunked
merge_unsorted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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