I am writing a PHP cli program that is a worker process for a queue system.
I assumed that PHP collects garbage from time to time in such a case, and won\'t constant
It comes down to this. You have to trigger garbage collection manually by calling gc_collect_cycles()
.
I have written a bunch of code to try and track this down and come down to two scripts:
This one doesn't crash:
for($i = 0;$i < 100;$i++) {
useMemory();
gc_collect_cycles();
}
And this one crashes:
for($i = 0;$i < 100;$i++) {
useMemory();
}
Here is a link to compare these scripts on Blackfire
As you can see, when you don't call gc_collect_cycles
it never happens, and you get to the memory limit, and PHP kills itself.
PHP doesn't even use this opportunity to GC itself. The reasoning behind this is discussed on the PHP-DEV mailing list, but basically comes down to complications of how to run __destruct
methods, that require memory, when the memory limit has been reached. (Also on the bug tracker #60982).
Memory usage func:
This is the code I used to 'waste' memory, it purposefully creates cyclic references that can only be cleaned by the garbage collector. Note that without these cycles the objects will be cleaned by reference counting as soon as they fall out of scope.
class Big {
private $data;
public function __construct($d = 0) {
for($i = 0;$i< 1024 * 10;$i++) {
$this->$i = chr(rand(97, 122));
}
}
}
function useMemory() {
$a = new Big();
$b = new Big();
$a->b = $b;
$b->a = $a;
}