Repository navigation
Work around globbing performance in Python 3.12 - #1696
Merged
Merged
Conversation
find_all_snippet_directories() expanded the wildcards Vim allows in 'runtimepath' entries with Path(anchor).glob(relative_path), i.e. it globbed the whole path starting at "/". Python 3.12's pathlib has no fast path for literal pattern components, so every entry listed "/", "/home", "/home/user", ... once. With ~100 runtimepath entries on a slow filesystem the first snippet expansion froze Vim for seconds, and an ancestor directory without list permission made the snippet directory vanish because Path.glob swallows the PermissionError. Literal entries are now a single existence check. Entries with a wildcard glob only the tail starting at the first wildcard component. Fixes #1694
Answers the review question whether snipMate file discovery shares the runtimepath glob problem. It does not walk from the filesystem root: its glob base is `<rtp>/snippets` and a missing directory costs one is_dir() per pattern. It never expanded wildcards in runtimepath entries at all though, so `snippets/` directories behind an entry like `~/.vim/bundle/*` were silently skipped while UltiSnips-format directories behind the same entry have been found since #1416. Move the helper to common.py as expand_runtimepath_entry() and use it for both sources. snipMate now honours the wildcards and skips entries without a snippets directory with a single existence check.
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.
find_all_snippet_directories()expands the wildcards Vim allows in'runtimepath'entries. Since the pathlib migration (c84bb5a) it did so withPath(pth.anchor).glob(str(pth.relative_to(pth.anchor))), i.e. it globbed the whole path starting at/.Python 3.12's pathlib has no fast path for literal pattern components: every component goes through _WildcardSelector
, whichscandirs the parent directory and callsis_dir()on each entry. With the ~100 entries of a plugin-heavy runtimepath that lists/,/home,/home/user`, ... once per entry (595 directory listings and 5763 stats in the report), and on WSL with symlinked network folders the first snippet expansion froze Vim for seconds.Neither 3.11 nor 3.13 have this issue. 3.11 pathlib resolved literal pattern segments through a single
stat. Python 3.12 removed that path in python/cpython#102710. Python 3.13 brought a literal fast path back in the glob rewrite (python/cpython#117732).We work around this by finding globbing in the snippet paths and only start globbing from the segment that has globbing characters. While strictly only needed for 3.12 it does not hurt on other Pythons.
Fixes #1694.