Add cold-eye cache and prefetch for CPU linear scan - #2351
Open
philsippl wants to merge 11 commits into
Open
Conversation
This was referenced Aug 19, 2026
philsippl
marked this pull request as ready for review
August 19, 2026 11:49
Prefetch reservations - Reservations are single-use and idempotent instead of use-counted. The same record was hinted by the known-candidate loop, by every first-eye chunk that matched it (reauth targets always do), and by both orientations, while stage two fetched it once after deduplication, so each reauth leaked a Ready entry until the 4096-record cap disabled prefetch for the rest of the process. The first fetch now consumes the reservation and promotes the value into the LFU, where a second consumer finds it. - The actor releases leftover reservations once a batch has finished all of its scans (IrisWorkerPool::release_prefetched), so reservations never outlive the batch that made them, including on error paths. - A failed prefetch read is logged and counted rather than latched for the next barrier. Its reservations are released, so the foreground fetch repeats the read and is the path that fails closed on a missing exact version; latching could fail a batch for a transient read the foreground would have served, or attribute an abandoned scan's error to the next batch. The db-backed test now asserts that contract. - Count prefetch hits under their own metric instead of as LFU misses. Rolling LUC window - A non-dense startup window keeps its newest contiguous run, an empty window starts at the first serial ID it sees, and a skipped serial ID restarts the window, all with a warning/metric instead of a panic; the window is a cache in front of the exact-version overlay, LFU, and database. Startup missing-row check uses a set instead of O(n^2). Configuration - Reject disable_persistence in linear-scan mode: the cold-eye mutation overlay is only released by result persistence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAbAnQyfsSrWH6UGcRM1FF
dkales
previously approved these changes
Aug 21, 2026
Comment on lines
+472
to
+478
| if search_mode == HawkSearchMode::LinearScan && disable_persistence { | ||
| bail!( | ||
| "exact CPU linear-scan mode requires persistence: the database-backed eye's \ | ||
| mutation overlay is released only when results are persisted \ | ||
| (SMPC__DISABLE_PERSISTENCE=false)" | ||
| ); | ||
| } |
Collaborator
There was a problem hiding this comment.
Is this not a blocker for a potential shadow mode?
Contributor
Author
There was a problem hiding this comment.
oh great callout, @gryaele will it actually be deployed without persistence?
Contributor
There was a problem hiding this comment.
hm, we need to deploy it with persistence
Contributor
There was a problem hiding this comment.
It will run in shadow mode with hnsw db.
|
|
||
| let mut db_size: usize = 0; | ||
| let mut cold_storage: Option<(Store, usize)> = None; | ||
| let mut cold_storage: Option<(Store, usize, usize, usize)> = None; |
Collaborator
There was a problem hiding this comment.
nit: this could be a struct by now
A fresh Cargo.lock hash makes the release build and tests consume nearly the whole 20-minute budget; the post-job cache upload is then cancelled, so every subsequent run is cold again and fails the same way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAbAnQyfsSrWH6UGcRM1FF
A broad-matching query (prod batch 201: ~3.7k discovered candidates, 22.8s compute) exposed three compounding cold-eye weaknesses: - Discovery enqueues one tiny prefetch command per full-scan chunk; with thousands of hits the 64-deep queue dropped most commands and the rest became single-row round trips, so almost nothing was prefetched. The worker now drains and merges everything queued into one reservation pass and one batched read per database round trip, and the queue holds 4096 commands. Barriers drained mid-merge complete after that read, preserving their ordering contract. - The candidates then stalled the scan on one giant foreground `id = ANY(...)` statement (~38 KiB TOASTed rows; Postgres logged multi-second slow statements). Large fetches, foreground and prefetch alike, are now split into 512-row sub-batches issued concurrently. - That foreground read had no metric, which is why dashboards showed "DB time is short" while Postgres disagreed. It now records linear_scan_cold_foreground_db_duration/_batch_size/_records_total, and the worker records the coalesced batch size. Also raise the cold-eye LFU capacity to 12288 records (~460 MiB, three times the previous size) so recurring broad-matcher candidates stay resident between requests instead of being refetched.
leonanos8
added a commit
that referenced
this pull request
Sep 2, 2026
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.
Summary
Adds the cold-eye data plane on top of the exact CPU linear-scan correctness baseline in #2347. This layer does not change matching thresholds, rotations, result semantics, or the resident-eye compute kernel.
How it works
(serial_id, version_id), invalidates them on mutation, and fails the request closed on a registry/database miss.The prefetch list excludes candidates already consumed by the concurrent known-candidate stage before reservations are created, preventing stale reservations from accumulating across requests.
Validation
cargo check -p iris-mpc-bins --bin iris-mpc-linear-scancargo clippy -p iris-mpc-cpu -p iris-mpc -p iris-mpc-bins --all-targets -- -D warningsdb_dependent; the deterministic full-server GPU/CPU result comparison and real-server benchmark are documented in Fused mirror scan, packed pair kernel, and lane pipelining for the CPU linear scan #2348.Review guide
iris-mpc-cpu/src/execution/hawk_main/iris_worker.rs.iris-mpc-cpu/src/execution/hawk_main/search.rs.iris-mpc-store.iris-mpc/src/server/mod.rsand the cache metrics/configuration.Stack