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
Browse filesBrowse the repository at this point in the historyBrowse files
Foster Guo
committed
perf: fold no-op transform scans into parent on ASCII text
When parent text is pure ASCII, transforms like VariantNorm, Romanize,
RomanizeChar, and EmojiNorm are guaranteed no-ops. Previously each
produced a redundant full DFA traversal of identical text with only a
different pt_index_mask. Now fold_noop_children_masks recursively merges
their masks into the parent's scan, eliminating redundant scans.
For {None, VariantNorm, Romanize, Delete} on ASCII text: 4 scans → 2.
Measured ~7-8% throughput improvement on multi-PT ASCII miss workloads.
Also adds noop_fold benchmark module to cover this path.
Copy file name to clipboardExpand all lines: DESIGN.md
+13Lines changed: 13 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -289,6 +289,19 @@ The threshold (0.67) was calibrated from an 8,932-point characterization sweep a
289
289
290
290
In `walk_and_scan`, density propagates through the transform tree via `TransformStep::output_density()` (conservative: returns parent density). The materialized path can refine this when the transform produces confirmed-ASCII output. `density == 0.0` replaces the old `is_ascii` boolean for transform no-op detection.
291
291
292
+
#### No-op Scan Folding
293
+
294
+
When the parent text is pure ASCII (`density == 0.0`), transforms like VariantNorm, Romanize, RomanizeChar, and EmojiNorm produce identical text (they only operate on non-ASCII codepoints). Scanning the same text again with a different `pt_index_mask` wastes an entire DFA traversal.
295
+
296
+
`fold_noop_children_masks` recursively merges no-op children's `pt_index_mask` into the parent's scan mask. The parent scans once with the OR'd mask; no-op children are skipped entirely during the walk. This is correct because:
297
+
298
+
- Each `PatternEntry` has a fixed `pt_index` — hits pass exactly one mask branch.
299
+
-`mark_positive` and `satisfied_mask |= bit` are idempotent.
300
+
- Matrix path uses the same `text_index` (`parent_vi`) — same column, same counters.
301
+
- The AC engine reports each position exactly once per scan.
302
+
303
+
For a matcher with PTs {None, VariantNorm, Romanize, Delete} on ASCII text, this reduces 4 scans to 2 (root+VN+Romanize merged, Delete separate), yielding ~7-8% throughput improvement on the scan-dominated path.
0 commit comments