You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #3069 / PR #3070. Estimated ~4-8% end-to-end on rule-pass-bound repos, on top of #3070's 3-7%.
Why
The required-literal prefilter (#3070) eliminates 62% of rule sweeps corpus-wide, but the per-file most expensive rules are structurally ungateable — their patterns bottom out in operators and generic identifiers every file contains. Measured on a 7.6MB single-segment C header (node/deps/simdjson/simdjson.h), the whole C rule pass is 5.2s and the top ungated rules are:
rule
finditer cost
anchored?
state_mutation
382ms
✅ `(?:^
args
245ms
❌
pointers
238ms
❌
api
216ms
partially (^typedef, ^(?!static…) branches)
func_start
176ms
✅ ^[ \t]*… (C/C++; TS's is unanchored)
A whole-segment substring gate can't help these. But the #3063 precedent ('=' in line before the var-decl backtracking regex, 8.2× on that pass, byte-identical results) generalizes to them as a per-line pass: split the segment into lines once, apply a cheap per-line membership test, and run the regex only on surviving lines.
Proposal
state_mutation first — it is literally perf(detector): skip =-less lines before the var-decl backtracking regex #3063 again. Every alternative of the pattern requires =, ++, or --; a line containing none of '=', '++', '--' cannot match. It is anchored to line-start-or-delimiter, and its classes exclude \n, so per-line evaluation is equivalent (verify the (?![^\n(]{0,300},[ \t]*$) lookahead's $ semantics under re.M when matching line-by-line — likely needs the line passed with its trailing content semantics preserved, or finditer per line rather than .match).
C/C++ func_start: ^[ \t]*-anchored, never spans newlines until the arg-list part — needs a hand-verified cheap line test (e.g. a line must contain ( to open an arg list).
python/go api/globals/decorators: same shape, smaller wins.
Where a rule is anchored but has no cheap universal line test, rule_prefilter.derive_literal_gate can be reused per line — the same one-of literal check against a 80-char line is ~free.
Per-rule opt-in via an explicit registry (e.g. _line_gates = {rule: test} alongside _scope_filters), NOT automatic derivation — each rule's "never spans a newline" and "line test is implied by every branch" claims must be individually argued and tested, exactly as #3063 did.
Extend tests/tools/gate_parity_audit.py with a per-line-gate leg: for every corpus file × line-gated rule, assert the per-line pass produces the identical match set (offsets included) to the whole-segment finditer.
Golden crucible both legs; keyword-rosetta 46/46 via verify_language.py --engine.
Micro-benchmark the per-line loop overhead: a Python-level line loop costs more per line than finditer costs per match on dense-hit rules, so each gated rule must show a measured win on hit-sparse and hit-dense files before shipping (the perf(detector): skip =-less lines before the var-decl backtracking regex #3063 var-decl loop set the pattern).
Estimate
state_mutation + func_start ≈ 11% of the C rule pass on the header micro-bench; the rule pass is roughly half of wall time on rule-bound repos (from #3070's A/B), and #3063-style gates historically recover most of a gated rule's cost on typical files. Hence ~4-8% end-to-end, concentrated on C/C++-heavy repos (curl, sokol-zig, node's vendored deps).
Minor extension while in there: positive-lookahead literal harvesting in derive_literal_gate (deliberately deferred in #3070) — (?=…literal…) content is required text; a handful more rules would gate.
Follow-up to #3069 / PR #3070. Estimated ~4-8% end-to-end on rule-pass-bound repos, on top of #3070's 3-7%.
Why
The required-literal prefilter (#3070) eliminates 62% of rule sweeps corpus-wide, but the per-file most expensive rules are structurally ungateable — their patterns bottom out in operators and generic identifiers every file contains. Measured on a 7.6MB single-segment C header (
node/deps/simdjson/simdjson.h), the whole C rule pass is 5.2s and the top ungated rules are:state_mutationargspointersapi^typedef,^(?!static…)branches)func_start^[ \t]*…(C/C++; TS's is unanchored)A whole-segment substring gate can't help these. But the #3063 precedent (
'=' in linebefore the var-decl backtracking regex, 8.2× on that pass, byte-identical results) generalizes to them as a per-line pass: split the segment into lines once, apply a cheap per-line membership test, and run the regex only on surviving lines.Proposal
state_mutationfirst — it is literally perf(detector): skip =-less lines before the var-decl backtracking regex #3063 again. Every alternative of the pattern requires=,++, or--; a line containing none of'=','++','--'cannot match. It is anchored to line-start-or-delimiter, and its classes exclude\n, so per-line evaluation is equivalent (verify the(?![^\n(]{0,300},[ \t]*$)lookahead's$semantics under re.M when matching line-by-line — likely needs the line passed with its trailing content semantics preserved, orfinditerper line rather than.match).func_start:^[ \t]*-anchored, never spans newlines until the arg-list part — needs a hand-verified cheap line test (e.g. a line must contain(to open an arg list).api/globals/decorators: same shape, smaller wins.rule_prefilter.derive_literal_gatecan be reused per line — the same one-of literal check against a 80-char line is ~free.Per-rule opt-in via an explicit registry (e.g.
_line_gates = {rule: test}alongside_scope_filters), NOT automatic derivation — each rule's "never spans a newline" and "line test is implied by every branch" claims must be individually argued and tested, exactly as #3063 did.Correctness bar (same as #3070)
tests/tools/gate_parity_audit.pywith a per-line-gate leg: for every corpus file × line-gated rule, assert the per-line pass produces the identical match set (offsets included) to the whole-segmentfinditer.verify_language.py --engine.finditercosts per match on dense-hit rules, so each gated rule must show a measured win on hit-sparse and hit-dense files before shipping (the perf(detector): skip =-less lines before the var-decl backtracking regex #3063 var-decl loop set the pattern).Estimate
state_mutation+func_start≈ 11% of the C rule pass on the header micro-bench; the rule pass is roughly half of wall time on rule-bound repos (from #3070's A/B), and #3063-style gates historically recover most of a gated rule's cost on typical files. Hence ~4-8% end-to-end, concentrated on C/C++-heavy repos (curl, sokol-zig, node's vendored deps).Minor extension while in there: positive-lookahead literal harvesting in
derive_literal_gate(deliberately deferred in #3070) —(?=…literal…)content is required text; a handful more rules would gate.🤖 Generated with Claude Code