| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
phpstan#5928 introduced LruCache for the parser's file-contents memo. Three more caches were doing the same bookkeeping by hand, so they now use it as well: - PhpClassReflectionExtension's shared member-cache order, where set() returning the evicted keys is what lets the four member maps drop the same key - FileTypeMapper's name-scope map memo, whose manual entry counter count() replaces - UsefulTypeAliasResolver's resolved local type aliases FileTypeMapper's cache treated a configured maximum of 0 as "keep one entry" rather than "no limit" as the others do, because its eviction loop ran before the insertion. That is preserved as-is; normalising it would change behaviour for anyone who set the parameter to 0. FileTypeMapper's resolvedPhpDocBlockCache is deliberately left alone: it does not touch entries on a hit, so it evicts in insertion order rather than by use, and moving it to LruCache would change its eviction policy rather than just its shape. Behaviour unchanged on an identical analysis: same errors reported, and the same cache footprint - 1168 name-scope map misses, 2 local type alias misses and 910 member-cache evictions before and after. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Please provide time/memory measurements. This is only worth it if it leads to improvements. |
Sorry, something went wrong.
|
Of course the LruCache refacoring is nice but should be separste from introducing the cache to new places. |
Sorry, something went wrong.
The four limits are only read where the LruCache is constructed, so holding them as promoted properties keeps per-instance state nobody reads and suggests the classes consult them later. Plain constructor parameters instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Double-checked this before it gets reviewed, and it earned two additions. Eviction is now actually exercised. The footprint numbers in the description came from a run with the shipped limits, where the type-alias cache only ever held two entries - so its eviction path was never touched. Re-ran the differential with the limits turned down, and with them at 0:
The second row is the one that matters for nameScopeMapMemoryCacheCountMax: 0: 237 misses on both sides. Had I passed the 0 straight through as "no limit", this branch would have shown far fewer misses, so that mapping is measured rather than argued. The type-alias eviction I forced separately on a fixture of 12 classes with local @phpstan-type aliases at resolvedLocalTypeAliasesCountMax: 1 - 12 misses and identical output on both sides. Second commit: the limits are no longer properties. All four - including CachedParser::$cachedSourceBytesMax from #5928 - are read only where the LruCache is constructed, so keeping them promoted left per-instance state nobody reads and implied the classes consult them later. They are plain constructor parameters now. Also checked and found nothing: no reference to the replaced properties survives anywhere in src/ or tests/, and the bounds are equivalent rather than off by one - the old code inserted and then evicted while over the limit, LruCache evicts before inserting, and both settle at exactly the configured maximum. CI: the three reds are the two Symplify integration jobs (composer 404 on the TomasVotruba/ecs zipball) and the Benchmark job, whose only failing case is bug-11283.php, already failing on 2.2.x itself - it showed +136% there earlier today against +72% here. Full suite 21334, self-analysis and phpcs clean. |
Sorry, something went wrong.
|
To be clear on the intent: this adds no caching and was not aimed at performance. It re-uses the LruCache from #5928 in the three places that were hand-rolling the same touch-and-evict logic, which is what @staabm asked for in #5928 (comment). Four hand-rolled LRUs become one with a unit test, net -23 lines. Measurements anyway, base 8e60b1adc against bc70f8e53, symfony 6.4 + doctrine vendor tree (3862 files, level 5), 5 interleaved rounds, medians:
The time deltas sit inside spreads several times their size, so read it as unchanged - no gain, no regression. The hit/miss footprint is identical too (1168 name-scope map misses, 910 member-cache evictions on both sides), which is the point: same caches, same behaviour, less code. If that cleanup is not worth carrying the abstraction, close it and I will not argue - the class stays in from #5928 either way. Two side notes. The second commit (the limits stop being properties, since they are only read where the cache is constructed) is a separate concern - happy to split it out. And FileTypeMapper::$resolvedPhpDocBlockCache, which I left alone because it evicts in insertion order rather than by use, is the one place where switching to LruCache does change something measurable: PHPDoc resolutions 12480 -> 12217 (-2.1%) on that corpus, identical output. Separate PR if you want it. |
Sorry, something went wrong.
|
Thank you! |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Follow-up to #5928, which introduced LruCache for the parser's file-contents memo. staabm asked in #5928 (comment) whether other places could use it - three could, and here they are.
Two deliberate non-changes:
Verification:
No new tests: these are behaviour-preserving conversions of existing caches, and LruCache itself has LruCacheTest from #5928.