Repository navigation
Remember annotation method and property lookups that find nothing - #6978
Merged
Merged
Conversation
The lookup recurses into the parent class and every interface, and getInterfaces() already includes the inherited ones, so the same ancestors are reached over and over. Only hits were cached, so a method without a @method tag anywhere in a wide, deep hierarchy was searched along every path again. Amp-Thread-ID: https://ampcode.com/threads/T-01a1ad6c-dec2-72ff-bbe8-5b3b62746c94
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.
AnnotationsMethodsClassReflectionExtensionandAnnotationsPropertiesClassReflectionExtensionlook for a@method/@propertytag by recursing into the parent class and every interface.ClassReflection::getInterfaces()already includes the inherited interfaces, so the same ancestors are reached along many paths. Only hits were cached, so a method with no@methodtag in the hierarchy was searched again on every path, which grows exponentially with depth.PhpClassReflectionExtension::createMethod()asks for each native method, so every method call pays for it.Both extensions now cache misses too, and the recursion into the parent and interfaces goes through that cache. The trait branch keeps calling the uncached walk, because there the declaring class is the using class and not the trait.
On
tests/bench/data/phpdoc-inheritance-speedup.php(10 levels × 3 interfaces), this walk was 74 % of the analysis time.Measurements
Instruction counts come from CodSpeed's CPU simulation (the harness from #6974, PHP 8.5.12):
Wall clock:
bin/phpstan analyse --debug, median of 6 interleaved runs per side, result cache cleared before each run, no turbo extension. Amp orb, Intel Xeon @ 2.60 GHz, 16 vCPUs, PHP 8.5.12 NTS:The benchmark still catches the regression it was written for (#4829): with this change applied on top of the commit before #4829, it takes 117 s user time, against 3.9 s on top of #4829 itself.
Under the CPU simulation it takes about 4 minutes instead of 39, so the longest benchmark shard in #6974 gets much shorter.
Neither class is shadowed by the turbo extension.