Skip to content

Instantly share code, notes, and snippets.

@ruudk
Created December 8, 2022 15:35
Show Gist options
  • Select an option

  • Save ruudk/41897eb59ff497b271fc9fa3c7d5fb27 to your computer and use it in GitHub Desktop.

Select an option

Save ruudk/41897eb59ff497b271fc9fa3c7d5fb27 to your computer and use it in GitHub Desktop.
How to find the files that are the slowest to analyze with PHPStan?

How to find the files that are the slowest to analyze with PHPStan?

For us, PHPStan became a bit slower with every release. We have a very large codebase with 10.000+ classes. There seem to be a few known issues related to big arrays.

See: phpstan/phpstan#8353 phpstan/phpstan#8146

To understand which files are problematic we run the following command:

vendor/bin/phpstan analyze --memory-limit=-1 --debug -vvv | tee phpstan.log

Then we run:

php parse.php
<?php
declare(strict_types=1);
$log = new SplFileObject("phpstan.log");
$logs = [];
$file = null;
while (! $log->eof()) {
$line = trim($log->fgets());
if ($line === '') {
continue;
}
if ($file === null) {
$file = $line;
continue;
}
preg_match('/took (?<seconds>[\d.]+) s/', $line, $matches);
$logs[] = [(float) $matches['seconds'], $file];
$file = null;
}
usort($logs, fn(array $left, array $right) => $right[0] <=> $left[0]);
$logs = array_slice($logs, 0, 100);
echo "Slowest files" . PHP_EOL;
foreach ($logs as $log) {
echo sprintf("%.2f seconds: %s", $log[0], $log[1]) . PHP_EOL;
}
@bcremer

bcremer commented Dec 20, 2022

Copy link
Copy Markdown

Thank you very much @ruudk.

I was able to shave off 2 minutes phpstan runtime (8 minutes to 6 minutes) by excluding module/*/config/module.config.php from the analysis in an Laminas MVC project.

@ruudk

ruudk commented Dec 20, 2022

Copy link
Copy Markdown
Author

@bcremer Happy to hear that!

PHPStan will soon get an option that displays the slow files too.

@szepeviktor

szepeviktor commented Dec 21, 2022

Copy link
Copy Markdown

For those who could use a shell one-liner:

vendor/bin/phpstan analyze --memory-limit=-1 --debug -vvv | sed -e 'N; s#\n# #; s#^\(\S\+\) .* \(\S\+\) s$#\2 \1#; /^ /d' | sort -n

@senki

senki commented Jan 2, 2023

Copy link
Copy Markdown

I made a rust version as part of a learning exercise.

(I hope this self-plug is OK)

@gnutix

gnutix commented Jun 23, 2023

Copy link
Copy Markdown

I got an undefined array key 'seconds' error, fixed by adding this piece of code after the preg_match call :

    if (!array_key_exists('seconds', $matches)) {
        continue;
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment