Noir::ReadPool
Reads files on a small pool of threads.
The detect walk used to read every file on the one thread that also runs
detection, so each open/read/close stalled everything else — on a
warm page cache macOS spends ~50µs of syscall time per file, and a cold
one waits on the disk. Reads are independent and touch no shared state,
so they can run in parallel; everything done with a file's content stays
where it was.
Callers get a reply channel per submitted path and receive from those in whatever order they need — the detector receives them in walk order, so registration order, detector dispatch and the content cache see exactly the sequence a sequential walk produced.
A worker never blocks on a reply (each reply channel holds one outcome), and every submitted path gets exactly one outcome, errors included: a missing reply would leave the receiver waiting forever.
Constructors
passive_rules run on every file that reads as text, on the pool's
threads: matching is a pure function of the content and the (immutable)
rules, and it was most of what the detect workers spent their time on
under -P.
Class methods
The threads are Noir::WorkerThreads', shared with the other pure work
a scan hands off, so the process never runs more than one small pool.