1461 1222 1186 1578 1673 1586 1326 1159 1425 1027 1247 1182 1820 1017 1416 1640 1473 1146 1501 1554 1331 1208 1350 1865 1322 1429 1349 1847 1068 1309 1117 1790 1831 1106 1062 1604 1497 1488 1691 1186 1999 1072 1159 1430 1800 1892 1992 1164 1219 1370 1921 1943 1626 1517 1713 1967 1842 1355 1438 1557 1587 1201 1472 1887 1918 1056 1626 1189 1304 1251 1615 1438 1318 1841 1361 1542 1052 1181 1625 1619 1260 1432 1284 1396 1758 1240 1519 1307 1034 1682 1463 1842 1445 1626 1522 1395 1783 1393 1170 From Minutes to Seconds: Massive Performance Gains in PHPStan | PHPnews.io


From Minutes to Seconds: Massive Performance Gains in PHPStan

Written by Ondřej Mirtes / Original link on Mar. 1, 2020


Strongly-typed object-oriented code helps me tremendously during refactoring. When I realize I need to pass more information from one place to another, I usually take my first step by changing a return typehint, or adding a required parameter to a method. Running PHPStan after making these changes tells me about all the code I need to fix. So I run it many times an hour during my workday. I don’t even check the web app in the browser until PHPStan’s result is green.

To encourage these types of workflows and to generally speed up feedback, I made massive improvements to its performance in the latest release. You can now run PHPStan comfortably as part of Git hooks or manually on your machine, not just in CI pipelines when you decide to submit your branch for a code review at the end of the day. Even on huge codebases consisting of hundreds of thousands lines of code, it finishes the analysis in seconds!

How was this achieved?

Parallel analysis

PHPStan now runs in multiple processes by default. The list of files to analyse is divided into small chunks which get processed by the same number of processes as the number of CPU cores you have. It works on all operating systems and doesn’t require any special PHP extension. And it’s enabled by default.

This feature was first released three weeks ago under an optional feature flag users had to turn on. The initial response from the early adopters was overwhelmingly positive:

 — @alex_schnitzler

 — @HugoAlliaume

 — @el_stoffel

 — @ftipalek

Result cache

Even with the improvements achieved by parallel analysis, there was one more opportunity to achieve an order-of-magnitude speed-up.

One idea that’s easy to come up with is to analyse only changed files. You might have seen a suggestion to run PHPStan like this:

# Don't do this!
git diff --name-only origin/master..HEAD -- *.php | xargs vendor/bin/phpstan analyse

First problem with this approach is that by changing one file, we can break a different file. For example if we add a method to an interface we need to reanalyse all the classes that implement the interface. We might miss out on real errors with this naïve approach.

Instead, we need to build a tree of dependencies between the files. So when we detect that A.php was changed, we analyse A.php+ all the files calling or otherwise referencing all the symbols in A.php.

Second problem is that even if we successfully mark all the right files that need to be reanalysed, we won’t see the errors from the remaining files. In order for users to not even notice they’re really analysing only a subset of files, we need to cache the list of errors from past analyses.

Hence the name: result cache.

We’ve been testing this feature at my day job @ Slevomat for the past year and it’s really solid. It’s now also enabled by default in the latest PHPStan release.

The cache gets invalidated, and PHPStan runs on all files again, if one or more of these items changed since the most recent analysis:

Especially the last item now makes the practice using git diff counter-productive. The list of analysed paths needs to remain stable for the result cache to be used. So the best practice is to always run PHPStan on the whole project.

If you want to run PHPStan without the result cache being used for some reason, you can use the new clear-result-cache command:

vendor/bin/phpstan clear-result-cache -c phpstan.neon && \
vendor/bin/phpstan analyse -c phpstan.neon -l 8 src/ tests/

I’m really excited about these improvements and can’t wait till you try them out! I’m looking forward to your feedback.

Do you like PHPStan and use it every day? Consider supporting further development of PHPStan on GitHub Sponsors. I’d really appreciate it!

If you’re a PHP developer, give PHPStan a shot. If you’re interested in various insights about software development, follow me on Twitter.

calevans krakjoe static-analysis ondrejmirtes

« React Query – Hooks for fetching, caching and updating asynchronous data in React - Binary Tools »