SIGN IN SIGN UP

perf(regex): cache compiled RE2 patterns across UserRegex constructions (#399)

* perf(regex): cache compiled RE2 patterns across UserRegex constructions

createUserRegex() recompiled its pattern on every construction. Commands that
build a UserRegex inside a per-row loop therefore recompiled the same pattern
once per row -- jq's test/match/capture/scan/splits/sub/gsub, awk's ~ and
sub/gsub/match/split, and sed's s/// (twice per line, for the g and
Nth-occurrence paths). Compiling costs ~23us against ~1.5us to match with an
already-compiled pattern, so compilation dominated those workloads.

Memoize the compiled RE2JS in a 256-entry cache keyed on the pattern and the
numeric RE2 flags, with insertion-order eviction, mirroring the glob regex
cache in src/utils/glob.ts. Only the compiled pattern is shared; lastIndex, the
reusable Matcher, result limits and the abort signal stay on the UserRegex
instance, which is still constructed per call.

Over 100k rows: jq test() 8.96s -> 4.26s, awk ~ 4.15s -> 2.55s, awk gsub
7.16s -> 6.10s, sed s///g 10.46s -> 8.29s. Commands that already hoisted
compilation out of their loop (grep, rg) are unchanged.

* perf(regex): skip caching patterns longer than 1024 characters

Patterns are user-controlled and unbounded in length, so a count-only cap
let 256 large distinct patterns pin their source and compiled programs
for the host process lifetime. Oversized patterns are now compiled but
not retained, bounding retained pattern source at 256 KiB.
W
Wei Tao committed
108c5ccf028e82bdcaabb2a5fd6b2640e56168f5
Parent: 2d9d41f
Committed by GitHub <noreply@github.com> on 9/7/2026, 8:00:54 PM