7

这与 PHP 5.3 Cli 应用程序有关,该应用程序以复杂的方式处理大量数据,需要数小时才能运行。有人发现关闭垃圾收集可以让它运行得更快(可能高达 50%)。

我遇到的唯一一篇提到这种性能影响的文章是http://derickrethans.nl/collecting-garbage-performance-considerations.html。我不确定我是否完全遵循它,但它似乎表明它仅适用于具有大量循环引用的代码。

有人可以对此有所了解吗?

另外,鉴于我们已经关闭了 gc,有没有办法手动减少内存?建议使用 unset()。一个快速测试表明,无论对象的大小如何,unset() 都释放了大约 80 个字节。这表明它只是取消了参考,我在网上阅读的内容证实了这一点。我是否认为当变量超出范围时,即使没有垃圾收集,这 80 个字节也会被释放?

4

2 回答 2

4

您刚刚禁用了循环引用 GC。常规的仍然有效。

常见的 GC 测试,无论是否有zvals(“内存”),不再被任何变量或属性引用,并将释放此内存。循环引用是指两个或多个对象直接或间接相互引用

$a = new stdClass;
$b = new stdClass;
$a->b = $b;
$b->a = $a;
unset($a, $b);

现在两个对象相互引用,但它们都没有从其他任何地方引用,所以它们是不可访问的。这就是循环引用 GC 试图检测的内容,但要找到它们,它会遍历每个已知对象并找出是否存在“来自外部”的引用。它有点复杂,但简化了 ;) 所以在有很多引用的结构中,尤其是循环的,这是一项艰巨的任务。

值得一提unset()的是:您只删除引用,但不要(直接)释放内存。这是由 GC 稍后完成的(它做得很好:))

于 2013-01-24T12:33:45.483 回答
2

您可以使用unset. __destruct您可以通过实现一个函数来清除类中的循环。unset所有引用其他对象的私有、受保护或公共变量。

如果您将其应用于现有程序,它会变得非常乏味,但它是可行的。


class A {
    public $ref;
    public function __destruct() {
        unset($this->ref);
        echo "destruct";
    }
}
$a1 = new A();
$a2 = new A();
$a1->ref = $a2;
$a2->ref = $a1;

不起作用

unset($a1, $a2);
echo "--";
// prints --destructdestruct (in 5.3)

这有效:

$a1->__destruct();
unset($a1, $a2);
echo "--";
// prints destructdestructdestruct-- (in 5.3)
于 2013-01-24T12:39:28.140 回答