lance-format / lance-format/lance

[Blobs V2] Bulk / coalesced reads for BlobFile

Open
#6,178 0 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
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

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

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.