-
-
Notifications
You must be signed in to change notification settings - Fork 947
File analysis/performance issue when file defines a global list of closures. #13933
Description
Bug report
tl;dr
This takes 20+ minutes:
require_once 'vendor/autoload.php';
$list = [];
// list of static closures
$list['alpha-1'] = static function (): App\Alpha\AlphaClass1 { return new App\Alpha\AlphaClass1(); };This takes 8 seconds:
require_once 'vendor/autoload.php';
// $list = [];
// list of static closures
$list['alpha-1'] = static function (): App\Alpha\AlphaClass1 { return new App\Alpha\AlphaClass1(); };Detailed explanation
In my project we don't use a full Symfony framework. We use a lot of components. One of the components that we don't use is a service locator and its compiler pass. That is why we add items to a Console component manually. Until now our code looked like this:
$application->add(new FooCommand(
$container->get(Dependency1::class),
$container->get(Dependency2::class),
$container->get(Dependency3::class),
));That was not efficient because all commands were created upfront even when not used.
We decided to do some refactoring and use FactoryCommandLoader that accepts an array where key is a command and value is a closure to create that command.
Finally, our code looked like this:
$list = [];
$list['foo:command'] = static function () :Command {
return new FooCommand(
$container->get(Dependency1::class),
$container->get(Dependency2::class),
$container->get(Dependency3::class),
);
};
// and so on for 460+ commandsAnd this basic change made phpstan to run in 20+ minutes instead of the previous 8 seconds.
I have tried to use ContainerCommandLoader and that also worked fine but that adds 460 entries into dependency injection container that are used only in this one place.
$list = []
$di->set(FooCommand::class, function (Container $container) : FooCommand {
return new FooCommand(
$container->get(Dependency1::class),
$container->get(Dependency2::class),
$container->get(Dependency3::class),
);
});
$list['foo:command'] = FooCommand::class;
// and so on for 460+ commandsThis has no negative effect on performance - it is similar to initial time. Difference is that here closure is provided as an argument instead value in an array.
I have prepared a repository that reproduces this issue:
https://github.com/GrzegorzDrozd/phpstan-performance-issue-reproduction
I am not sure that this is phpstan issue.
Code snippet that reproduces the problem
Expected output
Scanning should take similar amount of time.
Did PHPStan help you today? Did it make you happy in any way?
No response