Repository navigation
Share one NamespaceUses between the name scopes of a file - #6583
Merged
Merged
Conversation
The namespace and the use statements in effect at a point in a file are not specific to exported nodes. FileTypeMapper tracks the same data while building a name scope map, so move the value object and its tracker next to the name scopes where both can use them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0182BrC263VCQTibEPTJX2UY
Every IntermediaryNameScope held its own copy of the file's uses and constUses. serialize() writes arrays by value, so the name scope map FileTypeMapper stores in the file cache grew with the number of imports times the number of classes, functions and methods - and loading it could take more memory than building it from scratch. IntermediaryNameScope now refers to a NamespaceUses, and FileTypeMapper tracks the namespace and the use statements with NamespaceUsesTracker, which hands out one instance until the next namespace or use statement. serialize() keeps shared objects shared, so an entry stores the imports once per namespace and use-statement state. intern(), which restored the sharing only after the whole entry had been unserialized, and __set_state(), left over from the var_export()ed file cache, are no longer needed. Reproducer from the issue (572 imports, 1150 documented methods): largest file cache entry 27.7 MB -> 0.86 MB, consumed memory of a warm run 136 MB -> 8 MB (cold 36 MB -> 12 MB). The name scope map entries of src/Analyser src/Rules src/Type take 22.2 MB instead of 42.0 MB, peak RSS of that analysis is unchanged (579 MB). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0182BrC263VCQTibEPTJX2UY
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.
Every
IntermediaryNameScopeheld its own copy of the file'susesandconstUses.serialize()keeps shared objects shared but writes arrays by value, so the name scope mapFileTypeMapperstores in the file cache grew with the number of imports times the number of classes, functions and methods. Loading such an entry could take more memory than building it from scratch.Two commits:
ExportedNameScopetoPHPStan\Analyser\NamespaceUses(with its tracker, nowNamespaceUsesTracker). This is a pure rename. The tracker already hands out one instance until the nextnamespace/usestatement, and it duplicated whatFileTypeMapperdid by hand.NamespaceUsesbetween the name scopes of a file.IntermediaryNameScopenow refers to aNamespaceUsesinstead of carrying the arrays, andFileTypeMapperdrives aNamespaceUsesTrackerin place of its own namespace/use handling. A cache entry stores the imports once per namespace and use-statement state.intern()is removed. It restored the sharing only after the whole entry had been unserialized.__set_state()is removed. It was a leftover from thevar_export()ed file cache.v7.The
IntermediaryNameScopeconstructor loses its@apitag and changes signature. A GitHub code search finds it constructed only inside committed PHPStan cache directories, never in extensions.Numbers
Reproducer from the issue (572 imports, 1150 documented methods):
On
src/Analyser src/Rules src/Type(single process, warm file cache):intern()does not bring back the memory it was introduced to save.Test
FileTypeMapperTest::testNameScopeMapStoresImportsOnceuses a cache storage that serializes. It fails on 2.3.x: 10 copies of an import where 2 are expected. It also checks the names resolved from the stored entry, including ausestatement between two classes and a second namespace block.Supersedes #6577.
Closes phpstan/phpstan#15304
🤖 Generated with Claude Code
https://claude.ai/code/session_0182BrC263VCQTibEPTJX2UY