Skip to content

perf(parser): specialized fast path for default-option parsing#15

Merged
evoactivity merged 1 commit into
mainfrom
perf/tree-parser
Jul 19, 2026
Merged

perf(parser): specialized fast path for default-option parsing#15
evoactivity merged 1 commit into
mainfrom
perf/tree-parser

Conversation

@evoactivity

@evoactivity evoactivity commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Applies the experiment-loop methodology (4 parallel agents on isolated copies, winners combined and measured stepwise) to the tree parser, which had fallen behind the SAX engine after the recent perf rounds.

What went in

  • Thin parse() dispatcher: default-option calls route to a module-level parseRootFast with every option check constant-folded, pos as a true local (helpers inlined), and zero per-call closure allocation. Optioned calls take the untouched general path.
  • Deferred ignorable whitespace: whitespace-only text recorded as integer triples; pure element containers drop it with no substring allocation, mixed content materializes lazily.
  • Offset-based close-tag verification: flat range compare against the open tag's name offset — no substring().trimEnd() per close tag.
  • Fused text scan + classification, integer loop guards, inline attribute-name scan with a name="value" fast path, entity-decode gated on & presence.

Measured and rejected

Parallel-array stacks, bounded JS pre-scan before SIMD indexOf, switch reordering.

Results

fixture before after gain
small 1,367,666 1,687,050 1.23x
RSS 85,865 137,518 1.60x
SOAP 64,349 91,376 1.42x
Atom 35,517 52,689 1.48x
POM 13,759 20,580 1.50x
EPG 17,521 23,075 1.32x

Now 1.7-2.2x faster than tXml across fixtures. Confirmed in the browser demo (~318k → ~505k ops/s).

Verification

  • 838 tests pass, typecheck clean, char-codes block regenerated via scripts/generate-char-codes.ts (idempotent)
  • Parity harness: 7 fixtures × 8 option sets, identical trees and errors
  • 30,000-case differential fuzz vs the previous parser (random malformed docs × 14 option sets): zero mismatches

Trade-offs

parseRootFast duplicates ~430 lines of parseChildren logic (semantic changes must be made in both; the parity gate + suite guard this), and module-level scratch buffers assume parse is never re-entered mid-call (holds today — no user callbacks run during tree building). BENCHMARKS.md DOM table and README claims regenerated.

Routes default-option parse() calls to a module-level loop with option
checks constant-folded and no per-call closures. Adds deferred
ignorable-whitespace handling, offset-based close-tag verification,
fused text scanning, and an inline name="value" attribute fast path.
1.2-1.6x faster across fixtures; verified against the previous parser
with a 30k-case differential fuzz across option combinations.
@evoactivity evoactivity added the bug Something isn't working label Jul 19, 2026
@evoactivity
evoactivity merged commit f1d59f3 into main Jul 19, 2026
6 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant