Repository navigation
[perf] Collect short names in a single AST walk in ShortNameResolver - #8700
Merged
Merged
Conversation
resolveFromFile() built its short-name map with two separate full-AST traversals of the same stmts - one for class-like and Name nodes, one for docblock short names. The map is version-cached, so during a convergence loop it is rebuilt once per stmts-version bump, paying for two traversals each time. Merge both into a single traversal: the docblock short names are collected in the same callback, then fqnized and merged afterwards. Result is identical, the stmts tree is walked once instead of twice. Adds bench/short_name_resolver_traversal_bench.php, which forces a re-resolve on every call to isolate the rebuild cost.
TomasVotruba
force-pushed
the
tv-short-name-single-walk
branch
from
October 18, 2026 20:06
21ec2dd to
cd96b35
Compare
TomasVotruba
enabled auto-merge (squash)
October 18, 2026 20:06
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.
Why
ShortNameResolver::resolveFromFile()builds theshortName => FQNmap that feeds theuse-import conflict checks inClassNameImportSkipper. It built that map with two separate full-AST traversals of the same stmts:ClassLike+NamenodesPhpDocInfoper node)The map is version-cached, so during the file convergence loop it is rebuilt once per stmts-version bump - paying for two full traversals each time.
What
Merge both into a single traversal. Docblock short names are collected in the same callback, then fqnized and merged afterwards. The result is byte-for-byte identical, the stmts tree is walked once instead of twice.
Bench
Adds
bench/short_name_resolver_traversal_bench.php, which forces a re-resolve on every call (no cache hits) to isolate the rebuild cost. Measured on the name-heavybench/Source/ManyNamesSource.phpfixture, 40 repeats x 200 rebuilds, CPU time:~6% on this fixture. The per-node
PhpDocInfobuild still dominates the docblock pass, so the saving is the second raw-traversal pass itself.Tests
rules-tests/CodingStyle/ClassNameImport+tests/Issues+ Import/ShortName/Namespace filters all green. ECS and PHPStan level 8 clean.