{{ message }}
Conversation
Problem: Every NFA regexp compilation allocates and frees two temporary
scratch buffers, the postfix list and the fragment stack, even
though the NFA states themselves are already allocated in a
single block; this repeats for every pattern, e.g. the hundreds
of autocmd patterns and syntax items loaded when opening a file.
Solution: Keep the postfix list and the fragment stack allocated between
compilations, growing them only when a larger one is needed, and
free them once in free_regexp_stuff().
The backtracking engine already uses this approach: it keeps its "regstack"
and "backpos" scratch buffers across invocations, allocating them only when
not present, and frees them in free_regexp_stuff(). Apply the same reuse to
the NFA "post_start" postfix list and the post2nfa() fragment stack by making
them grow-only statics. Only the scratch memory management changes; the
compiled program and matching are unaffected.
Measured with callgrind (instructions retired), against baseline:
- opening a single C file: ~3%
- opening a Vim script file: ~2.5%
- cold start opening a file (full runtime): -3%
- repeated ":runtime! syntax/c.vim" (x40): -2.5%
- opening 51 real source files in a session: -2%
Signed-off-by: Jules Voisin <julien.voisin@example.com>
chrisbra
reviewed
Sep 15, 2026
chrisbra
left a comment
Member
There was a problem hiding this comment.
Thanks, I have only 2 minor style issue, but I can fix those while merging
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem: Every NFA regexp compilation allocates and frees two temporary
scratch buffers, the postfix list and the fragment stack, even
though the NFA states themselves are already allocated in a
single block; this repeats for every pattern, e.g. the hundreds
of autocmd patterns and syntax items loaded when opening a file.
Solution: Keep the postfix list and the fragment stack allocated between
compilations, growing them only when a larger one is needed, and
free them once in free_regexp_stuff().
The backtracking engine already uses this approach: it keeps its "regstack" and "backpos" scratch buffers across invocations, allocating them only when not present, and frees them in free_regexp_stuff(). Apply the same reuse to the NFA "post_start" postfix list and the post2nfa() fragment stack by making them grow-only statics. Only the scratch memory management changes; the compiled program and matching are unaffected.
Measured with callgrind (instructions retired), against baseline: