Skip to content

fix(encoding): honor LANCE_MINIBLOCK_MAX_VALUES in byte-stream-split - #9299

Open
jackylee-ch wants to merge 1 commit into
lance-format:mainfrom
jackylee-ch:fix/bss-miniblock-value-cap
Open

jackylee-ch wants to merge 1 commit into
lance-format:mainfrom
jackylee-ch:fix/bss-miniblock-value-cap

Conversation

@jackylee-ch

Copy link
Copy Markdown
Contributor

ByteStreamSplitEncoder::max_chunk_size hardcoded 1024 for f32 and 512 for f64 and never consulted MAX_MINIBLOCK_VALUES, which the other mini-block encoders respect. The docs describe LANCE_MINIBLOCK_MAX_VALUES as an upper bound on the values in a single mini-block chunk, so a user who lowered it below 1024 still got 1024-value chunks on BSS-encoded columns. Such files read back correctly -- lost tuning, not corruption -- and the default 4096 exceeds the byte budget, so default behavior is unchanged.

Take the smaller of the byte budget and the configured cap, rounded down to a power of two. The rounding matters: compress records a non-final chunk's length as chunk_size.ilog2(), so a cap of 300 would declare 256 for a chunk of 300. The floor is two, since log_num_values == 0 there is rejected on read.

Testing

cargo test --release -p lance-encoding --all-features (1832 passed), plus fmt and clippy with -D warnings. The cap arithmetic moved into a pure helper, testable without the lazy static; ignoring the cap fails the three cases below the byte budget. A second test covers multi-chunk output.

`ByteStreamSplitEncoder::max_chunk_size` returned a hardcoded 1024 for f32 and 512
for f64 and never consulted `MAX_MINIBLOCK_VALUES`, which `value.rs`, `binary.rs`
and `rle.rs` all respect. The encoding docs describe
`LANCE_MINIBLOCK_MAX_VALUES` as an upper bound on the values in a single mini-block
chunk, with no exemption, and prescribe lowering it when mini-block read
amplification saturates a constrained link. A user who profiled and set it below
1024 still got 1024-value chunks on exactly the float and timestamp columns BSS is
chosen for. Files written that way read back correctly, so this is lost tuning
rather than corruption; the default of 4096 is above the byte budget, so default
behavior does not change.

Take the smaller of the byte budget and the configured cap, rounded down to a power
of two. That rounding is not cosmetic: `compress` records a non-final chunk's length
as `chunk_size.ilog2()`, so a cap of, say, 300 would declare 256 values for a chunk
holding 300. The floor is two, because a non-final chunk carrying
`log_num_values == 0` is rejected on read.

## Testing

`cargo test --release -p lance-encoding --all-features` (1832 passed), plus
`cargo fmt` and clippy with `-D warnings`. The cap arithmetic is split into a pure
helper so it can be exercised without the process-wide lazy static; ignoring the cap
fails the three cases that set it below the byte budget. A second test covers
multi-chunk output, which had none: the existing round trips fit in a single chunk,
so nothing checked a non-final chunk's declared length.
@github-actions github-actions Bot added A-encoding Encoding, IO, file reader/writer bug Something isn't working labels Sep 16, 2026

@lance-gatekeeper lance-gatekeeper Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gate recommendation: approve.

The encoder now applies the configured cap while preserving power-of-two non-final chunk metadata, unchanged default chunk sizes, and the existing file-format contract. The focused coverage exercises both cap selection and multi-chunk framing.

@lance-gatekeeper lance-gatekeeper Bot added the K-approved Latest Gatekeeper recommendation permits acceptance. label Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-encoding Encoding, IO, file reader/writer bug Something isn't working K-approved Latest Gatekeeper recommendation permits acceptance.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant