Skip to content

[perf] Cache realpath() of skip patterns in FileInfoMatcher - #8699

Merged
TomasVotruba merged 1 commit into
rectorphp:mainfrom
SanderMuller:cache-skip-pattern-realpath
Oct 18, 2026
Merged

TomasVotruba merged 1 commit into
rectorphp:mainfrom
SanderMuller:cache-skip-pattern-realpath

Conversation

@SanderMuller

Copy link
Copy Markdown
Contributor

FileInfoMatcher::matchRealpath() calls realpath() on the skip pattern for every file the pattern did not match by string. PHP caches a successful realpath() lookup, but not a failed one. A wildcard pattern such as **/vendor/* never resolves, so every file pays one filesystem lookup per wildcard pattern.

The matcher now keeps the realpath() result of each pattern for the rest of the run, false included. Each pattern is still resolved, so a literal skip path that contains * still matches through realpath(). That case is why #5830 was reverted in #5831. #6783 named PathSkipper as a next step for the same kind of work.

I measured on Shopware v6.7.6.2 with its own rector.php, which leaves 1 file path and 3 wildcard patterns. The machine is an M4 Pro with PHP 8.5:

  • The matcher alone, over the 9,212 files the finder returns: 522 to 865 ms per pass before, 83 to 120 ms after. That is 3 interleaved runs of 5 passes per side, and both skip the same 7 files. A failed lookup costs more or less from run to run, so the absolute numbers move.
  • A warm process --dry-run: CPU median 4.1 s before, 3.5 s after, over 10 interleaved runs per side. The machine was busy, so wall times were too noisy to use. Three cold runs per side showed no difference within their noise.

The new test resolves two plain patterns against file paths that contain .., so only the realpath() comparison can match them. It fails when the cache is keyed by the file or by a constant.

PHP does not cache a failed realpath() lookup. A wildcard skip pattern like
"**/vendor/*" fails that lookup once for every file. The matcher now resolves
each pattern once per run, and keeps a false result too.
@TomasVotruba

Copy link
Copy Markdown
Member

LGTM, thanks 👍

@TomasVotruba
TomasVotruba merged commit 7aa3326 into rectorphp:main Oct 18, 2026
49 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants