Conversation
Contributor
|
ACTION NEEDED The PR title and description are used as the merge commit message. Please update your PR title and description to match the specification. For details on the error please inspect the "PR Title Check" action. |
LuQQiu
force-pushed
the
lu/fri-sp-remap
branch
from
September 15, 2026 21:18
afcc49b to
4faf9f5
Compare
LuQQiu
force-pushed
the
lu/fri-rowmap-cache
branch
from
September 15, 2026 22:07
2442bd1 to
8ff878a
Compare
LuQQiu
force-pushed
the
lu/fri-sp-remap
branch
from
September 15, 2026 23:11
4faf9f5 to
294e624
Compare
…cache A query that translates addresses through a tagged fragment-reuse history re-read the row-map label blocks on every call. Cache the labels in the session index cache in ~4 MiB chunks (32 blocks, keyed by transition fingerprint + chunk index), so each part of the row map is read at most once. The chunk unit keeps the entry count small (~48 at 100M rows, ~477 at 1B) while making each cold miss one large sequential range read. On a 20M-row fixture this cuts cold _fri reads from ~10,440 to ~17 per query. Cache-off behavior is byte-identical (regression test compares cached vs uncached point/batch/sweep translations). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DgAshYD7wVzPVdjXRuWPPs
LuQQiu
force-pushed
the
lu/fri-rowmap-cache
branch
from
September 15, 2026 23:11
8ff878a to
20b91b2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR builds on #9187 and provides the eleventh FRI implementation layer. It remains outside the preceding nine-PR native GitHub stack to avoid extending its cascading rebase chain. It caches stable-partition row-map label chunks used by version-1 FRI query translation. It introduces no protobuf or file-format changes, and the legacy version-0 FRI path remains unchanged.
Problem
The FRI reader already caches the decoded transition history and its
StablePartitionMapping. Opening the mapping also loads and validates the small counts matrix. However,RowMapReader::block_labelspreviously read label blocks directly from_fri/<map_id>/stable_partition.lanceand discarded them after translation.Consequently, different index pages and later queries repeatedly read the same row-map blocks:
On the 20M-row benchmark fixture, this produced approximately 10,000
_frireads per query. Increasing the index-cache capacity did not change the read count because the mapping object was cached while its label data was not.Chunk cache
The row map is divided into cache chunks containing 32 logical mapping blocks:
Each mapping block describes 65,536 source rows. A full chunk therefore contains 2,097,152 nullable
UInt16labels and occupies approximately 4 MiB when decoded, plus validity and array overhead.Chunks are stored in the existing session index cache under the
row-map-blocksnamespace. The structured cache key contains the transition fingerprint and chunk index, so immutable chunks can be reused across queries and dataset snapshots that share the same transition.RowMapReader::block_labelsnow performs:The cache's
get_or_insert_with_keypath also deduplicates concurrent loads of the same chunk. Address translation, counts validation, deletion handling, and destination-offset calculation are unchanged.Integration
frag_reuse_reader::open_mappinggives each stable-partition mapping an optionalRowMapBlockCache.StablePartitionMappingpasses it toRowMapReaderwhen the immutable row-map file is opened on first use.The default behavior enables chunk caching without eagerly reading labels. Two diagnostic controls support benchmarking:
LANCE_FRI_ROWMAP_CACHE=0disables the chunk cache and restores direct block reads.LANCE_FRI_ROWMAP_PREWARM=1loads all chunks concurrently when the mapping is opened.These environment variables are diagnostic controls rather than persisted dataset settings.
Relationship to index remapping
This PR optimizes the translating state before an index segment has caught up:
#9187 handles the later materialized state by rewriting a fully covered index segment onto destination addresses. Once that succeeds, the segment no longer reads the consumed row-map transitions during queries. This cache remains useful for segments that have not been remapped or cannot satisfy the full-coverage requirement.
The cache does not rewrite index files, modify transition metadata, release row-map payloads, or change cleanup behavior.
Memory behavior
The row-map file may be compressed on storage, but cached chunks hold decoded nullable
UInt16labels. A fully resident map therefore requires approximately two bytes per physical source row, plus validity and cache overhead:Row-map chunks share the existing cache budget with scalar and vector index state. A cache smaller than the combined working set may evict row-map chunks and index partitions from each other. Prewarming should therefore be used only when the cache can hold the intended working set.
Benchmark results
The benchmark measures the translating state after a stable-partition rewrite over a 20M-row local NVMe fixture:
_frireads_fribytesChunk caching reduced row-map requests by roughly 600 times and storage bytes by roughly 32 times. Local steady-state throughput remained similar because the uncached range reads were served cheaply by the operating-system page cache and query execution was compute-bound. The request reduction is intended primarily for object storage, where each uncached range read adds a network round trip.
A 64 MiB index cache thrashed when it could not hold the decoded row-map working set together with the IVF partitions, confirming that cache capacity remains part of the operating tradeoff.
Validation
Tests verify that cached point translation, batch translation, full sweeps, and prewarmed translation produce the same results as the uncached reader, including multi-chunk files and a short final chunk. Existing row-map validation and FRI reader suites remain unchanged in behavior. The read benchmark accepts an index-cache capacity through
SPBENCH_INDEX_CACHE_MBfor cache-size experiments.