Skip to main content

Module prefetch

Module prefetch 

Source
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_batch returns 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.