PHP何时在长时间运行的脚本中运行垃圾收集?


When does PHP run garbage collection in long running scripts?

我正在写一个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;
}