Skip to content

Commit d35a232

Browse files
authored
perf(fts): bound compound score-floor tie buffering (#8161)
## What is the performance issue? Compound FTS preserves exact `(score DESC, row_id ASC)` ordering by retaining every candidate tied at the kth score until modern document IDs are resolved to row addresses. Large BM25 tie groups therefore make the candidate heap, address-resolution input, and final sort proportional to the full tie population, even when `limit=1`. ## How does this PR improve performance? - Keep the final global top-k heap keyed by resolved row ID. - Bound unresolved score-floor candidates at `limit + 128`. - Resolve modern addresses in batches of at most 128 candidates. - If a partition exceeds the unresolved bound, load its resident address projection and retry only that partition with exact row-ID keys. - Preserve the legacy document path and the shared score-only competitive threshold. - Expose addresses resolved, batch count, peak batch size, score-floor overflow count, and peak buffered candidates as execution metrics. ## Measurement | Scenario / metric | Baseline | This PR | Benefit | | --- | ---: | ---: | ---: | | `limit=1`, 512 equal-score candidates; peak unresolved candidates (lower is better) | 512 candidates | 129 candidates | 3.97x smaller peak | Measured deterministically with the in-memory compound collector regression in the local macOS debug test profile. This table measures candidate working-set size, not wall-clock latency. Comparable MMLB latency and memory benchmarks have not yet been run, so this PR does not claim a latency or throughput improvement. ## Correctness A 384-row equal-score regression spans reversed committed segments and multiple modern partitions. It compares limited output with the exhaustive oracle, exercises both bounded batch resolution and overflow retry, and verifies the emitted resolution metrics. Linear: [OSS-1618](https://linear.app/lancedb/issue/OSS-1618/bound-compound-fts-score-floor-tie-handling-by-resolved-row-id) ## Validation - `cargo fmt --all -- --check` - `cargo clippy --all --tests --benches -- -D warnings` - `cargo test -p lance-index scalar::inverted::compound::tests --lib` (6 passed) - `cargo test -p lance compound --lib` (5 passed) - `git diff --check`
1 parent 5d1f900 commit d35a232

5 files changed

Lines changed: 509 additions & 153 deletions

File tree

rust/lance-index-core/src/metrics.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ pub const AND_CANDIDATES_SEEN_METRIC: &str = "and_candidates_seen";
77
pub const AND_CANDIDATES_PRUNED_BEFORE_RETURN_METRIC: &str = "and_candidates_pruned_before_return";
88
pub const AND_FULL_SCORES_METRIC: &str = "and_full_scores";
99
pub const FREQS_COLLECTED_METRIC: &str = "freqs_collected";
10+
pub const COMPOUND_ADDRESSES_RESOLVED_METRIC: &str = "compound_addresses_resolved";
11+
pub const COMPOUND_ADDRESS_RESOLUTION_BATCHES_METRIC: &str = "compound_address_resolution_batches";
12+
pub const COMPOUND_PEAK_ADDRESS_RESOLUTION_BATCH_SIZE_METRIC: &str =
13+
"compound_peak_address_resolution_batch_size";
14+
pub const COMPOUND_SCORE_FLOOR_OVERFLOWS_METRIC: &str = "compound_score_floor_overflows";
15+
pub const COMPOUND_PEAK_BUFFERED_CANDIDATES_METRIC: &str = "compound_peak_buffered_candidates";
1016

1117
/// A trait used by the index to report metrics
1218
///
@@ -85,6 +91,21 @@ pub trait MetricsCollector: Send + Sync {
8591

8692
fn record_freqs_collected(&self, _num_collections: usize) {}
8793

94+
/// Record compound FTS document addresses resolved for final row-ID ties.
95+
fn record_compound_addresses_resolved(&self, _num_addresses: usize) {}
96+
97+
/// Record bounded compound FTS address-resolution batches.
98+
fn record_compound_address_resolution_batches(&self, _num_batches: usize) {}
99+
100+
/// Record the largest compound FTS address-resolution batch.
101+
fn record_compound_peak_address_resolution_batch_size(&self, _num_addresses: usize) {}
102+
103+
/// Record unresolved score floors that required a resolved-key retry.
104+
fn record_compound_score_floor_overflows(&self, _num_overflows: usize) {}
105+
106+
/// Record a candidate-buffer high-water mark for compound FTS.
107+
fn record_compound_peak_buffered_candidates(&self, _num_candidates: usize) {}
108+
88109
/// Returns an optional sink for recording exact I/O statistics (bytes read,
89110
/// IOPS, and requests) performed on behalf of this collector.
90111
///

0 commit comments

Comments
 (0)