You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
perf: intern DataFile fields/column_indices to reduce manifest memory (#6477)
## Summary
- Change `DataFile.fields` and `DataFile.column_indices` from `Vec<i32>`
to `Arc<[i32]>` so that fragments with identical field lists share a
single heap allocation
- Add `DataFileFieldInterner` that deduplicates these slices during
manifest deserialization
- In homogeneous tables (the common case), every fragment carries the
same field list, so at 20M fragments this saves **~2.4 GB** of redundant
heap allocations
## Motivation
When dataset manifests grow large (>1 GB with millions of fragments),
opening the dataset becomes very expensive in terms of memory. Each
`DataFile` previously owned its own `Vec<i32>` for `fields` and
`column_indices`, even though in most tables every fragment has the
exact same field list. This PR deduplicates those allocations at
deserialization time.
### Per-fragment memory breakdown (before)
| Field | Size per fragment |
|-------|------------------|
| `fields: Vec<i32>` (10 fields) | ~64 bytes |
| `column_indices: Vec<i32>` (10 cols) | ~64 bytes |
| **Total redundant** | **~128 bytes x 20M = ~2.4 GB** |
### After this change
With interning, all 20M fragments share a single `Arc<[i32]>` allocation
(~80 bytes total instead of 2.4 GB).
## Changes
- **`lance-table/src/format/fragment.rs`** — Core struct change
(`Vec<i32>` → `Arc<[i32]>`), custom `Serialize`/`Deserialize` impls, and
`DataFileFieldInterner`
- **`lance-table/src/format/manifest.rs`** — Use interner during
manifest deserialization
- **`lance/src/dataset/fragment.rs`**, **`merge_insert.rs`**,
**`io/commit.rs`** — Tombstoning and field-remapping rebuilt as new
`Arc<[i32]>` instead of in-place mutation
- **`python/src/fragment.rs`**, **`java/lance-jni/src/fragment.rs`** —
FFI boundary conversions
- Various test files — Updated struct literals and assertions
## Compatibility
- No format change — protobuf schema is unchanged
- Serde JSON output is identical (custom impl serializes `Arc<[i32]>` as
`[i32]`)
- All public API signatures that take `Vec<i32>` (e.g.,
`DataFile::new()`, `Fragment::add_file()`) still accept `Vec<i32>` and
convert internally
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0 commit comments