如果我使用类似于下面代码的节点树结构,我是否需要担心循环引用?
我读过,PHP 使用内存分配机制,当涉及循环引用时,这会让垃圾收集器的生活变得非常困难。

我想知道的是:

  • 如果我的树仅包含几个节点(例如 25 个),这是否有问题?
  • 脚本结束时内存会被释放还是我会慢慢地给服务器带来问题?
  • 脚本执行过程中什么情况下会出现这个问题?
  • 手动销毁引用可以解决问题吗?我应该始终这样做吗?
class Node {
    private $parent;
    private $children;

    function addChild( Node $child ) {
        $this->children[] = $child;
        $child->setParent( $this );
    }

    function setParent( $parent ) {
        $this->parent = $parent;
    }
}

//eg
$node0 = new Node;
$node1 = new Node;

// nodes 1 and 2 have a circular reference to each other
$node0->addChild( $node1 );
有帮助吗?

解决方案

逐点:

  • 如果我的树仅包含几个节点(例如 25 个),这是否有问题?

除非你的节点是真正的怪物。

  • 脚本结束时内存会被释放还是我会慢慢地给服务器带来问题?

当解释器关闭时,所有内存都会被释放。

  • 脚本执行过程中什么情况下会出现这个问题?

我怀疑你不会有什么需要担心的,除非你有非常低的内存限制或非常大的动态数据结构。如果您有 25 个不经常创建/释放的节点,则不会出现问题。

  • 手动销毁引用可以解决问题吗?我应该始终这样做吗?

我会帮你的。当使用 Propel 将大型数据集加载到数据库中时,我们遇到了很多内存消耗问题,我们跟踪到循环引用未释放。我们的解决方案是调用一个清除所有引用的方法。

其他提示

也许是这样,但由于它在每个请求结束时都会抛出所有对象(除非您正在缓存),所以我认为许多 PHP 程序员不会担心这一点。

如果您正在用 PHP 编写命令行脚本,那么也许您有理由担心它,但在它变得值得担心之前,您必须编写一些非常复杂的 PHP 代码。如果是这样的话,你就有更大的问题了。

祝你好运。

考虑到大多数 PHP 页面的性质——即进程为网页运行并在完成后被丢弃——我相当怀疑这是一个问题。我以前没有见过循环引用的问题,并且使用它们也没有出现问题。根据我的经验,您会遇到更多仅涉及内存消耗的问题,但 PHP 5 已经通过不再仅复制对象和数组(除非另有说明)而在一定程度上缓解了这一问题。

PHP 5.3 将包含循环引用检测和销毁功能。这是一个可选设置,仅应在必要时使用它,因为垃圾收集器会影响性能,但它是为您的示例量身定制的。

立即开发,采取预防措施在 __destruct() 方法中显式取消引用,并在可能的情况下升级到 5.3。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top