-
-
Notifications
You must be signed in to change notification settings - Fork 946
Description
Bug report
It seems that there is a memory consumption regression in version 0.12.83 caused by this. Phpstan throws the following error when analysing the project:
mmap() failed: [12] Cannot allocate memory
PHP Fatal error: Out of memory (allocated 4665122816) (tried to allocate 4294967304
bytes) in
phar:///___/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeRes
olver.php on line 574
Since that line does $throwPoints = \array_merge($throwPoints, $branchScopeStatementResult->getThrowPoints()); it leads me to believe that it has something to do with the new exception funcionality. However, I do not understand phpstan internals so maybe I'm wrong. But it is definitely strange that it tries to allocate 4 more gigabytes.
Unfortunately, the project is not open source so I can't just link the source code here. But to give you a rough context it's about 5k PHP files with a total of about 600k LoC. I'm running phpstan with php 7.4 in a vagrant VM with 6 GB of RAM (barely enough to analyse the whole project with 0.12.82). (I also tried running it on host with a larger amount of RAM, but it was still not enough: Allowed memory size of 12884901888 bytes exhausted (tried to allocate 8589934600 bytes)). I'm not sure how much it matters but the project is not very well written with respect to @throws. Most of the methods don't have it and if it's there it's mostly just whatever phpstorm complained about. 😄
Perhaps using [$a, $b] instead of array_merge($a, $b) would be better for memory consumption? OFC it's not as nice of a data structure, but if it were to save gigabytes of memory usage it would seem worth it to me. Here is a small PoC with roughly what I suspect is going on:
<?php
ini_set('memory_limit', '1G');
$o = (object) [];
$node = [$o];
$intermediaryArrays = [];
for ($i = 0; $i < 10; $i++) {
//$level = array_merge($node, $node, $node, $node, $node); // flat
$level = [$node, $node, $node, $node]; // tree
$intermediaryArrays[] = $level;
$node = $level;
}
echo number_format(memory_get_usage()) . "\n";With "flat" it outputs: 626,070,984
With "tree" it outputs: 396,320
Expected output
Memory consumption should be roughly in line with 0.12.82 + a reasonable amount for the new functionality.