-
-
Notifications
You must be signed in to change notification settings - Fork 863
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[performance] Between 13.6 and 17.3 seconds to analyse an abstract class with 90 lines of code #9498
Comments
This bug report is missing a link to reproduction at phpstan.org/try. It will most likely be closed after manual review. |
It's caused by Carbon and the huge PHPDoc they have there. Try to remove references to Carbon and it's going to be fast. |
Wow, that's crazy. I mentioned "one of the legacy service class takes ~5.41 sec for 273 lines of code". It just so happens that there was a reference to Carbon in that file, used only in a diff --git a/legacy/.../SomeClass.php b/legacy/.../SomeClass.php
index 235bfe83b1..d34dbf7f38 100644
--- a/legacy/.../SomeClass.php
+++ b/legacy/.../SomeClass.php
@@ -2,7 +2,6 @@
namespace legacy\SomeNamespace;
-use Carbon\Carbon;
use DateTime;
use DateTimeImmutable;
use DateTimeZone;
@@ -86,8 +85,8 @@ public function someMethod($dateStart, $dateEnd, $timeZone
}
/**
- * @param Carbon|DateTime|DateTimeImmutable $dateStart
- * @param Carbon|DateTime|DateTimeImmutable|null $dateEnd
+ * @param DateTime|DateTimeImmutable $dateStart
+ * @param DateTime|DateTimeImmutable|null $dateEnd
* @param string $timeZone
*
* @return array So for each reference to Carbon in any PHP project, 5+ seconds are lost ?! Wouldn't there be a way to circumvent that ? |
maybe it helps to centralize references to carbon into a few classes, so you don't have to spread it across the app.
there are already a few open issues regarding this similar topic. its not that easy to solve. |
i ran into this same issue in one of my apps in the exact same way you did funnily enough; reading @staabm's blog and trying it myself from my investigation the first file phpstan analyzes that contains carbon takes a while, but subsequent calls take significantly less time (probably due to internal caching) i found that by removing carbon references in one class, the next class to be analyzed that contained carbon saw the overhead instead, so i don't think it's 5 seconds for each reference to carbon, just the first time it's referenced it takes a while from brief profiling of the issue, it was like ~25% of time analyzing the affected file was spent parsing phpdocs alone and i couldn't find any meaningful speed up, but i'm relatively new to profilers and php performance etc. so i'd easily overlook something |
Thanks for your answers! We analyse the legacy files and the new files separately in our project, so that's why the "Carbon cost" came twice. Now I've managed to remove this dependency entirely from our legacy code, so that's half the battle won. :) I'm wondering : how is it we don't have Attributes for PHPDocs ? I seem to remember reading here and there that parsing PHPDocs is way slower than reading native attributes, right ? |
Would it be possible to cache the parsed data? Since Carbon is coming from the vendor folder it could be assumed to be unchanged if the composer.lock is unchanged. The project I'm working on sees up to 15 minutes spent on analyzing the code and PHPStorm is often complaining because even single files take over a minute (which is it's ttl for external processes). |
I have the same but remove Carbon is not really an option though since it does more then the DateTime instance of PHP does. I have a basic class which takes 10s to analyse: <?php
declare(strict_types=1);
namespace History\Service;
use Carbon\Carbon;
final class HistoryService
{
public function __construct()
{
(new Carbon())->format('d-m-Y H:i');
}
} or: |
Yes it is a know issue. If it's critical to you and you can't work on phpstan it self you could make a fork/dummy version of Carbon where instead of a docblock it has concrete implementations. |
I don't think it's that big of a deal. It takes 5-10s the first time Carbon is encountered but after that the analysis is fast. So it doesn't slow down analysis percent-wise, just a constant of 5-10s. |
For the projects I work on (Laravel based) an average PR takes about always 2-3 minutes for PHPStan. Without cache it's about 9-12 minutes. If we take out Carbon and a hand full of Facades we are looking at about 30 sec without cache. Even analyzing a single file locally will often take about 30 sec. I get frequent complaints about it from our developers. If there is a concrete task for how this could be improved I would be happy to work on that. |
@AJenbo This is weird. It sounds like the work is done multiple times even if it should be done just a single time (or once per thread). Would be nice to replicate this problem so that we can investigate. |
It feels like it's once per thread, there are a few distinct places where the progress bar clearly freezes for a while. Afaik the GitHub Workers only have two threads. But also it doesn't scale particularly well since each thread is hit by the cost, from my testing we sort of hit a wall once we got to about 1-2 minutes (without caching) with 8 cores (tested all the way to 32). Note that Carbon contain multiple classes that have this issue so the more of Carbon is utilized by a project the worse this issue gets. I think Laravel project are also hit extra hard by this since they have there Facades which often rely on large phpdoc blocks for there type definitions. |
@ondrejmirtes ok the total time of 9-12 minutes for single threaded analysis is actually mainly caused by the Bladestan extension, where the minimal time of 2 minutes is mainly caused by the slow phpdoc parsing afaik. It's a bit tricky since one is causing a general slow down but the other prevents us from scaling our way out of it. I guess I will start by looking at improving Bladestan performance first since I have a decent understanding of it and it's probably the majority of the slow down until we start getting close to a couple of minutes to analyze a project. |
@AJenbo if you could create a repo with a reproducer, that would be awesome |
Solved it: phpstan/phpstan-src#2582 Please test this in PHPStan 1.10.32 once I release this :) Or right now in |
@ondrejmirtes ❤️ Project: Single file: Without BladestanProject: Single file: |
@AJenbo if you could create a repro for a file which bladestan is slow on I can look into it |
Not sure if useful but just for the record, I've launched
Edit: updated values |
Another update: The numbers in my previous post are not so relevant now, maybe the difference is more about a i/o fluctuation, not sure how to empirically test it. What I can say is that running |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Bug report
Hello there,
While reading @staabm's blog posts about improving performance in PHPStan, I tried running PHPStan using this script in our project to see which files take the most time to analyze. There were ~10 files that took 1-2 secondes (which is okay, they are quite complex), lots that took less than 1 sec, and... one that took 17.30s alone.
I was surprised to find out that it was "only" an abstract class of 90 lines of code. I then ran the analysis 4 more times, and got the following results: 17.30, 13.67, 13.61, 16.09, 14.05. In comparison, even the most complicated file from our
legacy
folder with 2300 lines of crappy code takes "only" 11.69 seconds.So "I think there's more to this class than meets the eye", as Gandalf would say... ;)
Here it is :
I hope sharing this may help you guys find some bottleneck in PHPStan (or a clue to fix some problematic typing in this class), so that we can shave off theses seconds from all our CI builds!
gnutix
PS: There are also two legacy files in our project that probably take longer than they should, but I can't share them publicly. One of them is a service class that takes ~5.41 sec for 273 lines of code, the other an old PHP file that processes some values to prepare a template's rendering that takes ~4.46 sec for 339 lines. Please let me know if you'd like to investigate those too, I could send them in private.
Code snippet that reproduces the problem
No response
Expected output
Faster analysis.
Did PHPStan help you today? Did it make you happy in any way?
I wanted to thank you for taking care of the planet by taking performance issues seriously. <3
The text was updated successfully, but these errors were encountered: