Skip to content

perf: indexed loose rules by mandatory signatures - #180

Merged
alyldas merged 2 commits into
mainfrom
perf/index-loose-signatures
Jul 23, 2026
Merged

perf: indexed loose rules by mandatory signatures#180
alyldas merged 2 commits into
mainfrom
perf/index-loose-signatures

Conversation

@alyldas

@alyldas alyldas commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Derive conservative mandatory two- and three-letter signatures from controlled loose-rule syntax, with bounded expansion and compatibility fallback for rules that cannot be indexed safely.
  • Scan normalized input through one shared signature automaton, record UTF-16 candidate start regions, and validate indexed rules only with anchored sticky matchers.
  • Preserve Unicode /iu case-fold matches in candidate indexing and keep negated classes that may consume letters off the mandatory-signature path.
  • Preserve compiled rule order, overlap behavior, taxonomy metadata, boundaries, stretch handling, digit/symbol obfuscation, hyphen-tail behavior, and fallback compatibility through differential coverage.
  • Add construction timing plus deterministic automaton structure and tracked-storage measurements to the profanity benchmark.

Validation

  • npm ci
  • npm test -- tests/loose-candidates.spec.ts
  • npm run check
  • npm run benchmark:profanity on origin/main and this branch

Benchmark Evidence

Baseline origin/main:

  • createProfanityFilter(): 7.5738 avg ms
  • check long clean: 0.9054 avg ms
  • check loose match: 0.0107 avg ms
  • analyze long late match: 1.0083 avg ms
  • censor long late match: 1.0452 avg ms
  • scanner check long clean: 0.8834 avg ms
  • scanner scan long late match: 1.0249 avg ms

This branch:

  • createProfanityFilter(): 3.9225 avg ms
  • build loose signature index: 0.4446 avg ms
  • check long clean: 1.0387 avg ms
  • check loose match: 0.0130 avg ms
  • analyze long late match: 1.1578 avg ms
  • censor long late match: 1.1779 avg ms
  • scanner check long clean: 1.0158 avg ms
  • scanner scan long late match: 1.1815 avg ms

The same-machine results show faster repeated filter construction and measured per-call candidate-accounting cost in the current corpus. The conservative index covers 121 of 148 built-in loose rules with 292 automaton nodes, 291 transitions, 343 outputs, and 34,682 tracked signature/bitset bytes.

Compatibility Notes

  • Public APIs and package exports are unchanged.
  • Compiled rule precedence, match metadata, UTF-16 source ranges, overlap order, wrappers, and scanner contract names remain unchanged.
  • Rules without a safe mandatory signature retain compatibility regex validation; first- and second-character guards remain conservative prefilters.

Closes #169

No publish, no merge, no tag/release.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

(source === `${base}+` || source === `${base}*`) &&
(base.startsWith("[^") || base === "[-._]");

P2 Badge Fall back for negated classes that can consume letters

This treats every quantified negated character class as a separator even when it can consume letters. A valid loose dictionary rule such as b[^\s]*a therefore receives the mandatory ba signature, but it also matches bxa; scanning x resets the automaton, so no candidate start is recorded and the regex is never evaluated. Only skip classes proven to exclude \p{L} (with corresponding digit handling), or leave these rules on the compatibility fallback path.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/matchers/loose-candidates.ts

alyldas commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the negated-class review finding in 568c656. Quantified negated classes are now skipped only when the controlled syntax proves that they cannot consume letters or numbers; rules such as b[^\s]*a remain on compatibility regex validation. A regression test confirms that bxa is still matched. The focused test, full package check, benchmark, and all checks for the pushed head pass.

@alyldas
alyldas merged commit 8c4ecbd into main Jul 23, 2026
4 checks passed
@alyldas
alyldas deleted the perf/index-loose-signatures branch July 23, 2026 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Match loose rules from indexed multi-character signatures

1 participant