Commit c367b89
committed
perf(zyn_peg): decide an alternative on the byte ahead of it
A choice tried each alternative in turn and unwound whatever the
failed one had run. Most of that work was doomed before it started:
82% of the instructions in one parse of the prelude ran inside an
alternative later thrown away.
Every rule now carries the bytes it can begin with, grown to a
fixpoint because rules call each other, and a choice guards each
alternative but its last against the byte ahead. An alternative that
byte rules out costs one test rather than everything it would have
run before failing.
Parsing the prelude falls from 21.61 ms to 10.67 ms, ahead in all six
interleaved pairs, with user CPU halved. Rule entries drop from 65,844
to 28,400, failed matches from 52,436 to 12,901, and peak memory from
64 to 22 MB, for 266 more instructions in the compiled grammar.
Anything the analysis is unsure of reads as any byte, so a guard never
skips an alternative that could have matched: a pattern matching the
empty string, a negated class, a repetition that skips whitespace
first, and a rule the fixpoint leaves with no bytes all turn the guard
off rather than narrow it. The 65 files of the corpus parse to the
trees the interpreter builds, and the ImagePipe grammar's tests carry
the analysis over a second grammar.1 parent c8c02a9 commit c367b89
2 files changed
Lines changed: 347 additions & 14 deletions
0 commit comments