Skip to content

Use predicate cache for all non-timestamp predicates - #6760

Draft
PSeitz-dd wants to merge 6 commits into
mainfrom
predicate_cache
Draft

Use predicate cache for all non-timestamp predicates#6760
PSeitz-dd wants to merge 6 commits into
mainfrom
predicate_cache

Conversation

@PSeitz-dd

@PSeitz-dd PSeitz-dd commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Use predicate cache for all non-timestamp predicates
    • use predicate cache only if there is a timestamp filter, but without the timestamp filter
  • populate entries across the complete split and reuse them for partial or fully covered windows
  • skip posting-list warmup on predicate-cache hits
  • execute queries directly when the predicate cache is disabled

PSeitz-dd and others added 4 commits September 2, 2026 19:06
Normalize timestamp ranges before installing the predicate cache node so
partial and fully covered windows use the same residual predicate key.
Preserve search-after cache-node distinction and test reuse in both
window directions.
Avoid building and executing the predicate cache warmup query when the
configured cache capacity is zero.
@PSeitz-dd
PSeitz-dd requested a review from a team as a code owner September 2, 2026 13:32
@PSeitz-dd
PSeitz-dd marked this pull request as draft September 2, 2026 13:36

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a447a98682

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +950 to +954
ctx_clone
.doc_mapper
.query(split_schema, query_ast.clone(), false, predicate_cache)
.map_err(|error| TantivyError::InvalidArgument(error.to_string()))?
.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid rerunning predicates when cache admission fails

When a cache entry is larger than the configured capacity, or the LRU cache cannot evict a recently accessed entry, MemorySizedCache::put silently rejects it. In that case the preceding predicate_warmup_query.count() has already scanned the complete predicate, but rebuilding the query here produces another CacheFillerQuery miss and scans the same predicate again during the actual search; because no entry is retained, every repetition of such a time-bounded query pays two full scans. Preserve the freshly computed hit set for this request or otherwise avoid rebuilding into another miss when admission fails.

Useful? React with 👍 / 👎.

&quickwit_storage::metrics::PREDICATE_CACHE,
),
key_hasher: CacheKeyHasher::random(),
enabled: config.capacity().as_u64() > 0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep virtual predicate-cache simulations enabled

When the real predicate-cache capacity is zero but CacheConfig.virtual_caches contains a nonzero shadow cache, deriving enabled solely from the real capacity disables the entire predicate-cache path. The early returns in get and put, together with leaf_search_single_split omitting the cache context, prevent MemorySizedCache from forwarding accesses and insertions to its virtual caches—the mechanism explicitly used to simulate alternate cache configurations—so the resulting experiment records no meaningful workload. Treat configured virtual caches as enabled for simulation purposes, or otherwise continue feeding their metrics while leaving the real cache disabled.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

no, there should be a way to disable to functionality. Which is currently to set the predicate cache to 0.

.and_then(|(cache, cache_split_id)| {
let timestamp_field = ctx.doc_mapper.timestamp_field_name()?;
let predicate_ast = time_bounded_cached_predicate(&query_ast, timestamp_field)?;
let predicate_key = serde_json::to_string(&predicate_ast).ok()?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Canonicalize predicate keys before serialization

For a time-bounded TermSetQuery spanning multiple fields, terms_per_field is a HashMap, so reparsing the same request can produce a different JSON field order each time. Serializing that AST directly as the predicate key therefore makes identical predicates probabilistically miss the cache, creating duplicate entries and repeatedly executing the new full-split predicate warmup. Build the key from a canonical representation, such as sorting map keys before serialization, so identical requests reliably reuse their entries.

Useful? React with 👍 / 👎.

@PSeitz PSeitz changed the title Cache reusable predicates for time-bounded searches Use predicate cache for all non-timestamp predicates Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants