lance-format / lance-format/lance
[Blobs V2] Bulk / coalesced reads for BlobFile
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 7.1k
- Forks
- 852
- Avg merge
- 3d 18h
- Merged PRs (30d)
- 272
Description
Motivation
Blobs are a crucial element for training workloads, where a dataloader requests a batch of 32-256 rows that include metadata as well as blobs (images, audio, etc.) per step and throughput matters more than random-access latency on any single blob. Currently, bulk-access performance is suboptimal: the only way to get concurrency from Python is wrapping individual BlobFile.readall() calls in a ThreadPoolExecutor.
Under the hood, take_blobs returns Vec<BlobFile>, where each BlobFile.read() issues an independent reader.get_range() call. This bypasses the FileScheduler coalescing logic that columnar reads benefit from. Reading N packed blobs that are sequential in the same .blob sidecar file results in N separate I/O operations, even when a single range read (or a few coalesced ones) would cover them all.
Proposed changes
1. Bulk read API
A method like Dataset::read_blobs(blob_files, concurrency) -> Vec<Bytes> that accepts the output of take_blobs and handles concurrent reads and coalescing on the Rust/tokio side, returning data directly. From Python this would be a single block_on call instead of requiring a ThreadPoolExecutor around individual BlobFile.readall() calls.
2. Read coalescing for blobs sharing a backing file
When multiple blobs reside in the same backing file (packed or inline), group them by path, merge adjacent/nearby byte ranges (similar to what FileScheduler::submit_request already does), issue fewer I/O operations, and slice the results back.
The Rust-side infrastructure for both improvements already exists (FileScheduler coalescing, futures::stream::buffered for concurrency) - it's mostly a matter of wiring it into the blob read path.
Related
#4947
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Trace the existing take_blobs output through BlobFile.read/readall and the FileScheduler::submit_request path, then review futures::stream::buffered for the proposed concurrency flow. Use the requested Dataset::read_blobs API as the entry point; done means bulk reads return ordered bytes while blobs sharing a backing file use fewer coalesced range requests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- api, data-engineering, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100