Skip to main content

Module pat_cache

Module pat_cache 

Source
Expand description

pat_cache submodule — global compiled-pattern cache (Rust-only opt). Global compiled-pattern cache — a zshrs-only optimization with NO C counterpart, so it lives here in src/extensions rather than in src/ported.

Why it exists: C zsh recompiles a pattern on every match too, but its C patcompile is ~40-75x faster than this Rust port. Shell code re-matches identical patterns constantly — [[ x == pat ]], ${(M)a:#pat}, case, ${x//pat/…} — and p10k’s _p9k_param re-matches the SAME (#b)prompt_([a-z0-9_]#)(*) thousands of times per precmd. At the port’s compile cost that dominated interactive startup (the “hang before prompt”). Caching the compiled program turns those repeats into a hash lookup + a cheap clone of the bytecode, and lets zshrs actually beat zsh here.

Safety: the compiled Patprog is self-contained — matching (pattry*) reads prog.0.flags / prog.0.globflags (never the global compile statics) and borrows the prog by & (read-only). So a cached clone is interchangeable with a freshly-compiled one.

Correctness of the key: the compiled output depends on the pattern text, inflags, and exactly six options — EXTENDEDGLOB/KSHGLOB/SHGLOB (which shape zpc_special in patcompcharsset) and CASEGLOB/CASEPATHS/MULTIBYTE (which shape patglobflags in patcompstart). All are folded into the key, so any option change yields a distinct key rather than a stale hit.

GLOBAL (not thread-local): the VM dispatches [[ … ]]/pattern work across zshrs’s worker threads, so a per-thread cache would miss on every worker. A single RwLock<HashMap> is shared: reads (the common case, a hit) take the read lock and run concurrently; only a miss’s store takes the write lock. The check runs BEFORE patcompile’s own compile mutex, so hits never serialise on the compiler.

Functions§

get
Look up a compiled pattern. Returns a clone of the cached Patprog on a hit (interchangeable with a fresh compile), None on a miss. Checks the lock-free thread-local L1 first, then the shared L2 (promoting an L2 hit into L1).
put
Store a freshly-compiled pattern in both cache levels.