Expand description
Input-archive page-cache prefetcher (D-20)
Input-archive prefetcher (D-20): warm the next batch of task input archives into the OS page
cache ahead of dispatch, so the ventilator’s inline /data read is served from RAM instead of
the cold QLC-RAID6 platter.
Measured cold read on /data is ~10 ms median per ~685 KB archive (p99 ~34 ms), which caps the
single-threaded ventilator at ~100 dispatches/s — the binding bottleneck at full-arXiv scale,
where the ~1 TB working set ≫ RAM so nearly every dispatch reads cold. (The 6.7 GB sandbox fits
in cache and hides this entirely.) A pool of warmer threads open + read → discard the upcoming
archives; the bytes land in reclaimable page cache — not dispatcher RSS — so this can never
OOM (the kernel drops the clean cache before the workers’ anonymous memory). It is the read-side
mirror of the sink’s D-7 writer fan-out, but leaves the dispatch loop untouched (D-4
ordering preserved): the ventilator still does its own File::open + read, now served warm.
Two bounds keep cache use sane (the prefetch is pure cache hygiene, not a correctness path — a warm that lags, is skipped, or fails just leaves a cold read exactly as before):
- a per-entry cap (
prefetch_max_entry_mb): a >cap monster is left for the ventilator’s existing chunk-streaming read (O(chunk) resident), not read twice into cache; - a per-batch byte budget (
prefetch_budget_mb): a batch that clusters large entries stops warming at the budget and cold-streams its tail, so it can’t churn out Postgres’s cache.
Structs§
- Prefetcher
- A pool of page-cache warmer threads fed a batch of input-archive paths per refetch. Disabled
(
input_prefetchers = 0) it is an inert no-op —Self::warm_batchreturns immediately and the ventilator reads inline exactly as before D-20. Held on the ventilator’s stack; dropping it (on ventilator shutdown/restart) disconnects the warmers and joins them.