我正在写一个PHP cli程序,这是一个队列系统的工作进程。
我假设PHP在这种情况下会不时地收集垃圾,并且不会经常达到内存限制。
情况似乎并非如此。
指出- 在PHP 7上运行
-
zend.enable_gc = 1
- 没有全局变量
归根结底是这样的。可以通过调用gc_collect_cycles()
手动触发垃圾收集。
我写了一堆代码,试图跟踪这个,并归结为两个脚本:
这个不会崩溃:
for($i = 0;$i < 100;$i++) {
useMemory();
gc_collect_cycles();
}
这个崩溃了:
for($i = 0;$i < 100;$i++) {
useMemory();
}
这是Blackfire上比较这些脚本的链接
正如你所看到的,当你不调用gc_collect_cycles
时,它永远不会发生,并且你达到内存限制,PHP杀死自己。
PHP甚至不会利用这个机会对自己进行GC。这背后的原因在PHP-DEV邮件列表中讨论过,但基本上归结为如何在达到内存限制时运行需要内存的__destruct
方法的复杂性。(同样在bug跟踪器#60982上)。
Memory usage function:
这是我用来"浪费"内存的代码,它有目的地创建只能由垃圾收集器清理的循环引用。请注意,如果没有这些循环,一旦对象超出作用域,就会通过引用计数清理它们。
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;
}