Skip to content

feat: add cache summary diagnostics#7818

Open
jackye1995 wants to merge 2 commits into
lance-format:mainfrom
jackye1995:jack/cache-placement-summary
Open

feat: add cache summary diagnostics#7818
jackye1995 wants to merge 2 commits into
lance-format:mainfrom
jackye1995:jack/cache-placement-summary

Conversation

@jackye1995

@jackye1995 jackye1995 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Adds read-time cache entry summary APIs for index and metadata caches, backed by optional cache entry inventory in Lance core.

Summaries aggregate by cache group, component, type, entry count, and weighted size so callers can avoid dumping raw cache keys.

Index cache components

Index cache summaries group entries by index cache prefix. For a normal index this is the dataset URI plus index UUID; when fragment-reuse state is involved the prefix also includes the fragment-reuse UUID. Within each index group, the component field is a compact category instead of the raw cache key.

Tracked index-cache components include:

  • ivf: IVF partition and sub-index entries from keys like ivf-*.
  • page: page-oriented scalar index entries from keys like page-*.
  • postings: inverted-index posting entries from keys like postings-*.
  • posting-list: ngram posting-list entries from keys like posting-list-*.
  • posting-metadata: inverted-index posting metadata from keys like posting-metadata-*.
  • positions: inverted-index position entries from keys like positions-*.
  • frag_reuse: fragment-reuse index entries from path-like keys such as frag_reuse/<uuid>.
  • type: scalar index detail entries from path-like keys such as type/<uuid>.
  • version: index metadata entries keyed by version numbers.
  • otherwise, the value type name is used so scalar values and other id-like keys do not expand the summary cardinality.

Example output

The Rust API returns CacheSummary structs. These examples show representative JSON-shaped renderings with illustrative counts and sizes.

Vector index

{
  "total_entries": 4,
  "total_size_bytes": 184320000,
  "groups": [
    {
      "cache_prefix": "s3://bucket/dataset/11111111-1111-1111-1111-111111111111",
      "entry_count": 4,
      "size_bytes": 184320000,
      "components": [
        {
          "component": "ivf",
          "type_name": "lance::index::vector::ivf::v2::PartitionEntry<...>",
          "entry_count": 4,
          "size_bytes": 184320000
        }
      ]
    }
  ]
}

FTS / inverted index

{
  "total_entries": 153,
  "total_size_bytes": 73400320,
  "groups": [
    {
      "cache_prefix": "s3://bucket/dataset/22222222-2222-2222-2222-222222222222",
      "entry_count": 153,
      "size_bytes": 73400320,
      "components": [
        {
          "component": "postings",
          "type_name": "PostingList",
          "entry_count": 96,
          "size_bytes": 50331648
        },
        {
          "component": "posting-metadata",
          "type_name": "PostingMetadata",
          "entry_count": 48,
          "size_bytes": 3145728
        },
        {
          "component": "positions",
          "type_name": "Position",
          "entry_count": 9,
          "size_bytes": 19922944
        }
      ]
    }
  ]
}

Scalar index

{
  "total_entries": 35,
  "total_size_bytes": 28311552,
  "groups": [
    {
      "cache_prefix": "s3://bucket/dataset/33333333-3333-3333-3333-333333333333",
      "entry_count": 35,
      "size_bytes": 28311552,
      "components": [
        {
          "component": "page",
          "type_name": "BTreePage",
          "entry_count": 32,
          "size_bytes": 25165824
        },
        {
          "component": "BTreeIndexState",
          "type_name": "BTreeIndexState",
          "entry_count": 1,
          "size_bytes": 2097152
        },
        {
          "component": "type",
          "type_name": "ScalarIndexDetails",
          "entry_count": 1,
          "size_bytes": 65536
        },
        {
          "component": "frag_reuse",
          "type_name": "FragReuseIndex",
          "entry_count": 1,
          "size_bytes": 983040
        }
      ]
    }
  ]
}

Summary by CodeRabbit

  • New Features

    • Added cache diagnostics APIs for enumerating cached entries and their sizes.
    • Added session-level summaries for index and metadata caches, including entry counts, total sizes, cache groups, and component breakdowns.
    • Summaries gracefully report when the configured cache backend does not support inventory.
  • Bug Fixes

    • Improved cache size accounting and ensured size calculations remain safely bounded.

@github-actions github-actions Bot added the enhancement New feature or request label Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The cache APIs now expose optional entry records with weighted sizes. The Moka backend supplies these records, and Session adds index and metadata cache summary APIs that aggregate counts, sizes, groups, and compact component names.

Changes

Cache diagnostics

Layer / File(s) Summary
Entry inventory contract
rust/lance-core/src/cache/backend.rs, rust/lance-core/src/cache/mod.rs
Defines public cache entry records and iterators, adds optional backend inventory, re-exports the types, and filters records by cache prefix.
Moka inventory and weighting
rust/lance-core/src/cache/moka.rs, rust/lance-core/src/cache/mod.rs
Centralizes logical-size and bounded-weight calculations, emits Moka entry records, updates size reporting, and tests prefix filtering and weight clamping.
Session cache summaries
rust/lance/src/session.rs
Adds index and metadata summary types and methods, aggregates records by cache group and component, compacts key names, and tests supported and unsupported backends.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: wjones127

Sequence Diagram(s)

sequenceDiagram
  participant Session
  participant LanceCache
  participant MokaCacheBackend
  Session->>LanceCache: request entry_records()
  LanceCache->>MokaCacheBackend: request prefixed inventory
  MokaCacheBackend-->>LanceCache: return CacheEntryRecord iterator
  LanceCache-->>Session: return filtered records
  Session->>Session: aggregate counts, sizes, and components
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: new cache summary diagnostics APIs and supporting inventory plumbing.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
rust/lance-core/src/cache/moka.rs (1)

175-182: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use the same bounded weight for approximate accounting.

approx_size_bytes() sums uncapped logical sizes, while eviction, size_bytes(), and inventory records cap each entry at u32::MAX. Large entries therefore produce conflicting cache-size diagnostics.

Proposed fix
         self.cache
             .iter()
-            .map(|(key, entry)| logical_entry_size(key.as_ref(), entry.size_bytes))
+            .map(|(key, entry)| entry_weight(key.as_ref(), entry.size_bytes))
             .sum()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/lance-core/src/cache/moka.rs` around lines 175 - 182, Update
approx_size_bytes to apply the same u32::MAX cap used by eviction, size_bytes(),
and inventory accounting when summing each logical entry size. Preserve the
existing synchronous cache iteration and ensure the resulting approximate total
is based on bounded per-entry weights.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rust/lance-core/src/cache/backend.rs`:
- Around line 28-30: Complete public API documentation across
rust/lance-core/src/cache/backend.rs:28-30, 73-83, and 145-152;
rust/lance-core/src/cache/mod.rs:289-301; and rust/lance/src/session.rs:26-69
and 308-349. Add compiling examples and relevant intra-doc links using the
actual CacheEntryRecord, inventory methods, backend implementation, summary
types, and current method signatures; document unsupported inventory behavior,
prefix-filtered record collection, relationships among the three summary levels,
and index/metadata summary usage.

In `@rust/lance/src/session.rs`:
- Around line 369-400: Update summarize_cache_records to return a fallible
result, such as Result<Option<CacheSummary>>, and replace every saturating_add
used for entry counts and byte totals with checked arithmetic. Propagate
overflow as a descriptive contextual error, including both aggregate and
per-component/group accumulation, and update callers to handle the new result
instead of silently producing a clamped summary.
- Around line 605-712: The new tests do not follow repository conventions for
test URIs and parameterized cases. In test_session_cache_summaries, replace the
dataset URI with plain "memory://"; convert
test_cache_key_component_names_are_compact into an rstest parameterized test
using readable named #[case::{name}(...)] cases for each input and expected
component.

---

Outside diff comments:
In `@rust/lance-core/src/cache/moka.rs`:
- Around line 175-182: Update approx_size_bytes to apply the same u32::MAX cap
used by eviction, size_bytes(), and inventory accounting when summing each
logical entry size. Preserve the existing synchronous cache iteration and ensure
the resulting approximate total is based on bounded per-entry weights.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c4ff2ba9-15c0-4f0e-b56f-8d5fb0c4624e

📥 Commits

Reviewing files that changed from the base of the PR and between 9681621 and c7ebb0f.

📒 Files selected for processing (4)
  • rust/lance-core/src/cache/backend.rs
  • rust/lance-core/src/cache/mod.rs
  • rust/lance-core/src/cache/moka.rs
  • rust/lance/src/session.rs

Comment thread rust/lance-core/src/cache/backend.rs Outdated
Comment on lines +28 to +30
/// Iterator over cache entries currently known to a backend.
pub type CacheEntryRecordIterator<'a> = Box<dyn Iterator<Item = CacheEntryRecord> + Send + 'a>;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Complete documentation for the new public cache-diagnostics surface.

The new public APIs have descriptive prose but lack required examples and cross-links.

  • rust/lance-core/src/cache/backend.rs#L28-L30: add an iterator usage example and link CacheEntryRecord.
  • rust/lance-core/src/cache/backend.rs#L73-L83: demonstrate record inspection and link the inventory methods.
  • rust/lance-core/src/cache/backend.rs#L145-L152: document backend implementation and unsupported-inventory behavior.
  • rust/lance-core/src/cache/mod.rs#L289-L301: demonstrate collecting prefix-filtered records.
  • rust/lance/src/session.rs#L26-L69: cross-link the three summary levels and show their relationships.
  • rust/lance/src/session.rs#L308-L349: add compiling index and metadata summary examples.

As per coding guidelines, “Document all public APIs with examples and links to relevant structs and methods; keep examples synchronized with actual signatures.”

📍 Affects 3 files
  • rust/lance-core/src/cache/backend.rs#L28-L30 (this comment)
  • rust/lance-core/src/cache/backend.rs#L73-L83
  • rust/lance-core/src/cache/backend.rs#L145-L152
  • rust/lance-core/src/cache/mod.rs#L289-L301
  • rust/lance/src/session.rs#L26-L69
  • rust/lance/src/session.rs#L308-L349
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/lance-core/src/cache/backend.rs` around lines 28 - 30, Complete public
API documentation across rust/lance-core/src/cache/backend.rs:28-30, 73-83, and
145-152; rust/lance-core/src/cache/mod.rs:289-301; and
rust/lance/src/session.rs:26-69 and 308-349. Add compiling examples and relevant
intra-doc links using the actual CacheEntryRecord, inventory methods, backend
implementation, summary types, and current method signatures; document
unsupported inventory behavior, prefix-filtered record collection, relationships
among the three summary levels, and index/metadata summary usage.

Source: Coding guidelines

Comment thread rust/lance/src/session.rs Outdated
Comment thread rust/lance/src/session.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rust/lance/src/session.rs`:
- Around line 473-483: Update checked_cache_summary_add to return the internal
error variant instead of Error::invalid_input for checked_add overflow,
preserving the existing diagnostic message. Add an overflow test for this helper
that asserts both the internal error variant and the message content.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6bbc390f-ae29-4c5c-9feb-5058fc270baa

📥 Commits

Reviewing files that changed from the base of the PR and between c7ebb0f and 8b7c513.

📒 Files selected for processing (4)
  • rust/lance-core/src/cache/backend.rs
  • rust/lance-core/src/cache/mod.rs
  • rust/lance-core/src/cache/moka.rs
  • rust/lance/src/session.rs

Comment thread rust/lance/src/session.rs
Comment on lines +473 to +483
fn checked_cache_summary_add(
current: usize,
increment: usize,
context: impl AsRef<str>,
) -> Result<usize> {
current.checked_add(increment).ok_or_else(|| {
Error::invalid_input(format!(
"Cache summary overflow while adding {increment} to {} (current value: {current})",
context.as_ref()
))
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Classify summary overflow as an internal diagnostic failure.

These values come from backend inventory, so Error::invalid_input incorrectly blames the caller. Return an internal error and add an overflow test asserting both variant and message.

Proposed fix
-        Error::invalid_input(format!(
+        Error::internal(format!(
             "Cache summary overflow while adding {increment} to {} (current value: {current})",
             context.as_ref()
         ))

As per coding guidelines, “Match the Error variant to the root cause” and “Assert on both the error variant and the message content in tests.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn checked_cache_summary_add(
current: usize,
increment: usize,
context: impl AsRef<str>,
) -> Result<usize> {
current.checked_add(increment).ok_or_else(|| {
Error::invalid_input(format!(
"Cache summary overflow while adding {increment} to {} (current value: {current})",
context.as_ref()
))
})
fn checked_cache_summary_add(
current: usize,
increment: usize,
context: impl AsRef<str>,
) -> Result<usize> {
current.checked_add(increment).ok_or_else(|| {
Error::internal(format!(
"Cache summary overflow while adding {increment} to {} (current value: {current})",
context.as_ref()
))
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/lance/src/session.rs` around lines 473 - 483, Update
checked_cache_summary_add to return the internal error variant instead of
Error::invalid_input for checked_add overflow, preserving the existing
diagnostic message. Add an overflow test for this helper that asserts both the
internal error variant and the message content.

Source: Coding guidelines

@wjones127
wjones127 self-requested a review July 16, 2026 06:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant