lance-format / lance-format/lance

perf: the IVF shuffle sorts a key tuple per row when partition ids are already bucketable

Open
#9,381 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

performance
Dominant language
Rust
Stars
7.1k
Forks
852
Avg merge
3d 18h
Merged PRs (30d)
272

Description

Description

sort_to_interleave_indices in rust/lance-index/src/vector/v3/shuffler.rs decides the row order for a shuffle flush group by building one (part_id, batch_idx, row_idx) tuple per row and sorting them:

let mut keys: Vec<(u32, u32, u32)> = Vec::with_capacity(total_rows);
// ... one push per row ...
keys.sort_unstable_by_key(|k| k.0);

The sort key is a partition id, which is already known to live in [0, num_partitions) because the very next loop rejects anything outside that range. Bounded keys do not need a comparison sort: counting the rows per partition, turning the counts into prefix sums, and scattering each row into its partition's run gives the same grouping in two linear passes and needs no 12-byte tuple per row.

The function runs once per flush group inside spawn_cpu, and a group is up to shuffle_partition_batches batches, 10240 by default, so n reaches millions of rows per call on a real build.

Measured in release, alternating both implementations in one process on uniformly distributed partition ids:

rows batches partitions key sort counting sort
1,048,576 1024 256 15.2 ms 2.00 ms
1,048,576 1024 4096 15.3 ms 1.92 ms
8,388,608 8192 4096 125.5 ms 20.3 ms

About 7x, and the gap grows with n rather than staying constant.

Expected behavior

Bucket the rows by partition id in O(n + num_partitions) instead of sorting n keys, keeping the null and out-of-range rejections the current code performs.

Lance version

13.0.0-beta.4 (main)

Language binding

Rust

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in rust/lance-index/src/vector/v3/shuffler.rs at sort_to_interleave_indices, and read how it validates partition ids and handles nulls. Reproduce the release measurements if possible, then verify that the resulting rows remain grouped by partition while both rejection behaviors are preserved and the implementation avoids sorting one tuple per row.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
performance
Issue type
Refactor
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.