Improve ReflectionEnum->getCases() performance#1410
Improve ReflectionEnum->getCases() performance#1410staabm wants to merge 8 commits intoRoave:6.30.xfrom
ReflectionEnum->getCases() performance#1410Conversation
|
@staabm yes, the best optimization would be to remove the adapter layer from PHPStan :) |
|
I'm OK with merging this, but it will eventually be re-factored again to an I'm convinced method tracing is actually inflating this more than it actually is relevant. I'd rather memoize |
FWIW, |
|
|
||
| $mappedCases = []; | ||
| foreach ($cases as $case) { | ||
| if ($this->betterReflectionEnum->isBacked()) { |
There was a problem hiding this comment.
This method call is repeated in the loop: let's pull it out of here
I feel |
|
You need to spend a couple months writing FP (Rust, Haskell, clojure, etc.), and then C-style loops start looking like the garbled mess that they are ;-) |
| @@ -530,14 +530,18 @@ public function getCase(string $name): ReflectionEnumUnitCase|ReflectionEnumBack | |||
| /** @return list<ReflectionEnumUnitCase|ReflectionEnumBackedCase> */ | |||
There was a problem hiding this comment.
Consideration here: we perhaps return list<ReflectionEnumUnitCase>|list<ReflectionEnumBackedCase> rather than list<ReflectionEnumUnitCase|ReflectionEnumBackedCase> 🤔
There was a problem hiding this comment.
AFAIK phpstan is not able to differentiate it, but I can do it if you prefer
There was a problem hiding this comment.
It's more precise for the consumer regardless, no?
There was a problem hiding this comment.
yeah. I already changed it silently :)
done |
|
please advice on how to make psalm happy or how/where to move this thing ;) |
|
I can try helping later tonight, but currently stuck with another issue at work. |
|
My opinion - this kind of micro optimization isn't worth it. It's only showing 8 % improvement in PHPStan because it's working with huge amounts of data. Once the root cause in PHPStan is fixed then the improvement isn't going to be 8 %, but barely measurable. The root cause was already fixed: phpstan/phpstan-src#2985 |
|
Most likely, but spiking memoization as a general outcome is still worth pursuing :D |
|
I am fine with closing it |
src/Util/Memoize.php
Outdated
|
|
||
| namespace Roave\BetterReflection\Util; | ||
|
|
||
| /** @template T */ |
There was a problem hiding this comment.
I'm thinking of this, meanwhile:
/**
* @template T
* @internal do not touch: you have been warned.
*/
final class Memoize
{
private readonly mixed $cached;
/** @param pure-Closure(): T $cb */
public function __construct(private Closure|null $cb) {}
public function get(): mixed {
if ($this->cb) {
$this->cached = ($this->cb)();
$this->cb = null;
}
return $this->cached;
}
}This could be used general-purpose on most adapters, if needed.
There was a problem hiding this comment.
mostly what you wrote, except I don't care if $cached is null (valid result)
There was a problem hiding this comment.
thanks - copied it over. the SA tools don't like it ;)
There was a problem hiding this comment.
Well, that's good :D
We are indeed bending the rules here: hence the @internal stuff as well.
I'll likely need to take over on this: a good measure of error suppression will be needed, but the impure-closure bit is most annoying (it shouldn't consider it impure 🤔 )
the method is showing up in profiles of phpstan/phpstan#10772
I am aware that this PR will not fix the root cause of the perf problem, but its a low hanging fruit on my way :)
lets remove the
array_mapmagic and the unnecessary closure invocation