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
Large memory comsumption #4072
Comments
Hi, how big is the project you're analysing? How many files? What does PHPStan report at the end when you run it with |
Same issue here, I am at 8 threads max, using 6gb RAM on a project with 6969 files (stuck at 1620). Edit: I've rerun the generation on a computer with a lot more RAM, it maxed out at 30GB consumption and 32 threads full usage. |
I'm running PHPStan on a project with 10k files and 3GB RAM is enough for it. Most likely it has a problem with a few big files with some structure that it gets stuck on. For example files like this https://github.com/arron0/phpstan-issue-4026/blob/master/src/TexyConvert.php can consume a lot of RAM. You should run with |
@ondrejmirtes Facing the same problem (excessive RAM usage making BB pipelines fail), I would like to investigate, but |
Alright, if you run
Implemented in: phpstan/phpstan-src@29f8938 |
Phpstan scan in my project 3626 files and when I try
Most files consume 0-10MB but some my presenters consume 220 MB but I don`t know what is wrong with these files because look like similar as each other files. Memory is not free continuously? |
Same observation here: I have a file that shows "0 B" and it is quite similar to another that shows ~ 120 MB. @ondrejmirtes can I send you those two files privately? |
I have project with 5500 files organized into several modules, memory limit for PHPStan set to 2 GB. |
Does anyone have any tool recommendation to investigate memory leaks? |
https://blackfire.io/ is the best on the market. |
I tried it but the memory output isn't very useful. Can you use it to find the memory leak @szepeviktor? |
Using level 0/1/2/3 didn't change consumed memory. |
Maybe fixes by #4401? |
@fezfez Thank you very much for your investigation. I can see a clear improvement using 0.12.70 compared to 0.12.68, but still not enough for me to use it on Bitbucket Pipelines. With my project, it's working fine in BB Pipelines with 0.12.25 and it works most of the time with 0.12.48, but any version after 0.12.48 have a excessive memory footprint... On your results in #4435, would you mind also comparing with versions 0.12.25, 0.12.48, 0.12.49? How exactly do you get the memory footprint? Do you use |
@pyguerder i use -debug -vvv and i try with 0.12.25 but it dont give memory info.... |
@pyguerder You can probably lower your total memory footprint by using less threads: https://phpstan.org/config-reference#parallel-processing |
@ondrejmirtes thanks, I did that already. Here are my observations: With version 0.12.25, it works with 2 threads in 2-3 min. I'm thinking that more memory optimizations could bring versions > 0.12.70 to the memory footprint of 0.12.25 so I could use more threads and fasten the pipelines... Thanks for all your work! Best regards |
@ondrejmirtes Thanks for recent memory optimizations, it helps a lot. |
@KacerCZ It'd make matters worse.
|
PHPStan 0.12.71 should be a bit better again performance and memory-wise, please test it and report back, thank you :) |
@ondrejmirtes Thanks! I have set up a small script to report memory consumption and execution time on two of my project (a small one and a big one). You can see the script here: https://pastebin.com/kRgmx1Sf And the results here: https://pastebin.com/WQ6LqWdF (big project) I hope it can provide useful information. Best regards |
Maybe https://github.com/arnaud-lb/php-memory-profiler from @arnaud-lb can help finding memory leaks here. I have a codebase, that needs a total of 4.21 GB (PHPStan
I was not able to collect profiling data, because I had no idea where to put If someone points me to the right direction I can profile that on my machine. |
@alfredbez If you were able to isolate that file that consumes 400 MB on its own to a separate repository, I might be able to look into it and come up with an optimization. |
@alfredbez I had a memprof branch that can dump the profile when the memory is exceeded, so I've just pushed it here: arnaud-lb/php-memory-profiler#47. With this change, you don't need to call |
Nice! I'll take a look into that tomorrow👍 |
I managed to profile the file I mentioned with the branch @arnaud-lb provided (thanks for that 👍), not sure if that can help here: Looks like
I tried that yesterday, but it failed. I could give you access to the private repository if that helps. |
I also analyzed that with blackfire, you can have a look at this here: https://blackfire.io/profiles/568084d9-776d-4593-b552-64a27142be37/graph |
Now we're talking. |
Note, that the callgrind-file shows a run that was running into the memory-limit ( |
Thanks @alfredbez! The profile data shows who caused the allocation of all the memory at the time of the exhaustion. The "Inc." and "Excl." columns show the exact amount of memory for each function. The number of calls is usually less significant. Sorting by "Incl" or "Excl both point at the parser. Intuitively, I would say that:
Note that memprof eliminates freed memory from the profile data, so the profile shows "live" memory only, not memory that was already freed. |
btw, here's the file I was analyzing, it basically overwrites this codeblock: <?php declare(strict_types = 1);
namespace Pyz\Zed\Stock\Persistence;
use Generated\Shared\Transfer\StoreTransfer;
use Orm\Zed\Stock\Persistence\SpyStockProductQuery;
use Spryker\Zed\PropelOrm\Business\Runtime\ActiveQuery\Criteria;
use Spryker\Zed\Stock\Persistence\StockRepository as SprykerStockRepository;
class StockRepository extends SprykerStockRepository
{
/**
* @param string $abstractSku
* @param \Generated\Shared\Transfer\StoreTransfer $storeTransfer
*
* @return \Orm\Zed\Stock\Persistence\SpyStockProductQuery
*/
protected function queryStockProductByProductAbstractSkuAndStore(string $abstractSku, StoreTransfer $storeTransfer): SpyStockProductQuery
{
return $this->getFactory()
->createStockProductQuery()
->useSpyProductQuery(null, Criteria::LEFT_JOIN)
->filterByIsActive(true)
->useSpyProductAbstractQuery(null, Criteria::LEFT_JOIN)
->filterBySku($abstractSku)
->endUse()
->endUse()
->useStockQuery(null, Criteria::LEFT_JOIN)
->filterByIsActive(true)
->useStockStoreQuery(null, Criteria::LEFT_JOIN)
->useStoreQuery(null, Criteria::LEFT_JOIN)
->filterByName($storeTransfer->getName())
->endUse()
->endUse()
->endUse();
}
} Two of the used classes are also on Github:
A third one just extends <?php declare(strict_types = 1);
namespace Orm\Zed\Stock\Persistence;
use Spryker\Zed\Stock\Persistence\Propel\AbstractSpyStockProductQuery as BaseSpyStockProductQuery;
class SpyStockProductQuery extends BaseSpyStockProductQuery
{
} |
@alfredbez Please create a small reproducing repository that shows the high memory consumption. |
@alfredbez that's very interesting: I am using the same structure on half of my projects, based on the Propel ORM (Propel2 in my case). I'm wondering if changes like this one can reduce (or increase) PHPStan memory consumption: https://github.com/propelorm/Propel2/pull/1657/files |
@pyguerder I tried that on my project, but it still shows the high memory consumption. The memory usage increased even (but only a bit, from 543 MB to 545 MB on my test). |
I investigated on my side and found a simple explanation concerning memory consumption in my case. I observed that nearly 60% of the RAM consumption is due to applying preg_replace to the PHPDoc: I suspected some memory leak in preg_replace but I could not find any (after quick search). I tried to replace As I wrote, the explanation is quite simple: I use the Propel2 ORM, which generates classes with a lot of PHPDoc. For simple models, the base Query class contains a single PHPDoc of 7.6 KB. For my most complex Query class, there is a single PHPDoc of 107 KB! Example:
I think those lines are essential to PHPStan because they define explicitly some methods that will be actually executed by the @ondrejmirtes Do you think there is a way to optimize memory consumption in that case? Maybe by clearing some references after getPhpDocKey is performed? I hope this provides useful information. Sorry if it is too specific to my case and may not benefit to the more general case of this issue... |
@pyguerder Memory used by preg_replace is most probably released immediately. Your report shows sum of how many memory it allocated during entire run not how much memory it helds simultaneously at any given time. |
@pyguerder Could you try to get xhprof snapshots? It could give better info where memory is allocated and not released. |
@pyguerder I just commited a little microoptimization that does no longer call |
@ondrejmirtes using the last commit of phpstan-src (using |
Yeah so @MartinMystikJonas is right, this isn't the reason. Better to revert that. |
@MartinMystikJonas @ondrejmirtes I did not manage to generate memory snapshots with xhprof but I could do it with Blackfire: https://blackfire.io/profiles/032a8d59-5e65-4d18-935d-b01b3d1b3eee/graph Does this provide useful information? Best regards |
phpstan 0.12.88 Tried to remove phpstan phpdoc from the file (6 methods like this) with Propel2 classes in use and memory consumption decreased from 247.16 MB to 46.5 MB |
But the real problem is still when nested query objects are used:
|
Can everyone here try PHPStan 1.0 to see if memory consumption improved? There was quite a lot of improvements in this direction. |
@ondrejmirtes just upgraded our CI/CD flow to work with the latest version and it started failing because of excessive memory usage. Running verion 0.12.x did not have this issue. Any idea? |
@kdckrs Please run PHPStan with |
@ondrejmirtes on my side, unfortunately, it is not significantly better than with 0.12.x, meaning my pipelines will only work if I reduce the number of threads. With my projects, high memory consumption is clearly related to big Propel queries as above. Splitting them in multiple blocks can improve the situation, but in my opinion, it reduces code readability. Regards |
@ondrejmirtes when I run it with |
@kdckrs With You should go through the |
Just checked that on our project and it looks better now with version 1.4.2, cut's the memory usage in half 🎉 |
Awesome! I feel good about closing this. |
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. |
Large memory cunsumption in bitbucket pipeline
I have 6GB RAM available for phpstan and I run phpstan with following command:
My phpstan.neon
`parameters:
Do somebody known why is 6GB RAM not enough? It is some way to decrease memory limit consumption?
The text was updated successfully, but these errors were encountered: