Fix #8349: Improve phpdoc parsing performance of huge stub files#5089
Closed
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Closed
Fix #8349: Improve phpdoc parsing performance of huge stub files#5089phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
- Skip PHPDoc string parsing during FileTypeMapper name scope map creation for doc comments that don't contain @template or type-alias tags - During createPhpDocNodeMap(), only template tags and type alias names are extracted from PHPDocs, so comments without these tags don't need parsing - Uses fast str_contains() checks on the raw doc comment string to decide whether to invoke the full PHPDoc parser - For a file with 10,000 function stubs, reduces processing time from ~4s to ~2s by avoiding ~10,000 unnecessary PhpDocStringResolver::resolve() calls - Added performance regression test in FileTypeMapperTest
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.
Summary
When PHPStan processes a large stub file (like WordPress stubs with thousands of function declarations),
FileTypeMapper::createPhpDocNodeMap()parses every PHPDoc comment in the file throughPhpDocStringResolver::resolve(). However, during name scope map creation, the parsed PHPDoc nodes are only used to extract@templatetags and type alias names (@phpstan-type,@phpstan-import-type, etc.). For files where most PHPDocs only contain@param/@return/@vartags, this parsing work is wasted.This PR makes the PHPDoc parsing lazy: doc comments are only parsed during name scope map creation if they contain template or type-alias related tags, detected via fast
str_contains()checks on the raw string.Changes
shouldParseDocComment()method tosrc/Type/FileTypeMapper.phpthat checks if a doc comment contains any of the tag patterns that require parsing during name scope map creation:@template,-template(for@phpstan-templateetc.),@phpstan-type,@psalm-type,@phan-type,import-type(for@phpstan-import-typeetc.)createPhpDocNodeMap()to only call$this->phpDocStringResolver->resolve($docComment)whenshouldParseDocComment()returns truetestLargeStubFileLazyPhpDocParsing()test intests/PHPStan/Type/FileTypeMapperTest.phpthat generates a 10,000-function stub file and verifies template type resolution still works correctly, with a timing assertion that catches the performance regressionRoot cause
FileTypeMapper::createPhpDocNodeMap()eagerly parsed all PHPDoc comments in a file to build the name scope map, even though only template tags and type alias names are needed at this stage. For large stub files with thousands of entries, this unnecessary parsing dominated the processing time. The fix adds a fast pre-filter that checks the raw doc comment string for relevant tag patterns before invoking the full PHPDoc parser.Test
Added
testLargeStubFileLazyPhpDocParsinginFileTypeMapperTestwhich:@param/@returnPHPDocs) plus a@templateclassFileTypeMapper::getResolvedPhpDoc()and verifies template type resolution works correctlyFixes phpstan/phpstan#8349