perf(kernel): keep only recently used name patterns in the regex cache

Merged
BO
16d ago
+57-7

Each resolver worker thread kept every regex it compiled for name checks in a thread-local map that only cleared at 4,096 entries. Since #382 added many more callers, a worker indexing CPython held 1,948 to 3,926 compiled regexes, about 151 to 334 MB per thread. A regex takes about 49 KB when compiled and about 85 KB once it has been searched. The map also outlived resolver recycles, so all six workers kept their regexes for the whole run.

This change replaces the map with two small generations of 256 entries. A hit in the older generation moves the entry to the newer one; when the newer one fills, the older one is dropped. A worker meets about 10,000 distinct patterns but reuses a few hundred at a time, so the hit rate stays about where it was (an LRU simulation on one worker's 228,709 lookups showed 1,024 entries match the old hit count, and 512 cost about 900 extra compiles out of about 11,000).

Measurements

Same host, Node, full index, run-capped. Node and edge counts matched the base in every run.

CorpusPeak memory beforePeak memory afterTime beforeTime after
CPython (2 runs)5.86 to 5.87 GiB4.25 to 4.35 GiB33.3 to 35.7 s32.9 to 33.8 s
pretix (2 runs)3.54 GiB3.0 GiB9.4 to 9.7 s9.5 to 9.6 s
django (1 run)3.86 GiB2.30 GiB11.3 s11.2 s
linux fs/ (2 runs)no changeno change15.6 to 17.3 s15.4 to 17.9 s

Generations of 512 gave 4.78 to 4.88 GB on CPython; 128 gave no further gain.

Checks

  • cargo test for the new unit test generations_bound_size_and_keep_reused_keys, which checks the entry bound, that a reused key survives, and that an old key is evicted.
  • Full Vitest suite: 575 files, 7,342 tests pass.
  • readme-sync passes.
  • Astra (xhigh) review: no actionable findings.

README rows checked

  • The note under the full-index table now records the CPython and pretix peak-memory figures above. The table itself was not re-run.
  • The sync and MCP rows and the "About this fork" tables are unaffected.