This performance optimization is contributed by keulinho, which with his knowledge on usage of blackfire, provided various PRs on performance optimizations:
- https://github.com/rectorphp/rector-src/pull/3485
- https://github.com/rectorphp/rector-src/pull/3495
- https://github.com/rectorphp/rector-src/pull/3501
- https://github.com/rectorphp/rector-src/pull/3502
- https://github.com/rectorphp/rector-symfony/pull/381
- https://github.com/rectorphp/rector-symfony/pull/382
What happened?
- Memoization resolved data
On various use cases, data can be hit in multiple rules, again and again, that's worth cached, for example:
/**
* @var array<string, bool>
*/
private array $skippedFiles = [];
public function shouldSkip(string | object $element, string $filePath): bool
{
if (isset($this->skippedFiles[$filePath])) {
return $this->skippedFiles[$filePath];
}
$skippedPaths = $this->skippedPathsResolver->resolve();
return $this->skippedFiles[$filePath] = $this->fileInfoMatcher->doesFileInfoMatchPatterns($filePath, $skippedPaths);
}
Above save data with index $filePath to a property, which the service is shared so it won't hit again.
- Avoid object creation when not needed, for example:
Before
if (! $this->isObjectType($methodCall->var, new ObjectType('ReflectionFunctionAbstract'))) {
return false;
}
return $this->isName($methodCall->name, 'getReturnType');
After
if (! $this->isName($methodCall->name, 'getReturnType')) {
return false;
}
return $this->isObjectType($methodCall->var, new ObjectType('ReflectionFunctionAbstract'));
Above, no need to create new ObjectType() when the name is not getReturnType, which faster.
In the CodeIgniter 4 project, it already show twice faster:
Before
After
Another future improvements effort
- Moving away from
parentlookup after node found byNodeFindertoSimpleCallableNodeTraverser, like this this PR:
Above:
✔️ We know that we search specific Node, which is Assign node with local property
✔️ No need to traverse deep when we found anonymous class ( new class ) and inner function inside ClassMethod
- Replacing lookup all nodes to only found first node, like this PR:
Above:
✔️ Instead of get all nodes by instance, and search name later, we find first found instance and directly verify the name.
Start feel the speed. Run composer update!
Happy coding!