views:

654

answers:

4

If I am using a tree structure of nodes similar to the code below, do I have to worry about the circular reference?
I have read that PHP uses a memory allocation mechanism which can make life very hard for the garbage collector when there are circular references involved.

What I want to know is:

  • If my tree consists of only a few nodes, say 25, is this a problem?
  • Will the memory be freed at the end of the script or am I slowly creating a problem for the server?
  • Under what circumstances will this problem have an effect during script execution?
  • Will manually destroying the references solve the problem and should I always do it?
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 );
+3  A: 

Maybe so, but since it throws out all objects at the end of every request (unless you're caching), I don't think many PHP programmers worry about this.

If you're writing command line scripts in PHP, then maybe you've got a case for worrying about it, but you'd have to be writing some pretty convoluted PHP code before it becomes something worth worrying about. And if that's the case you have bigger problems.

Good luck.

Allain Lalonde
In addition, there is the __destruct() method.
Richard Levasseur
+2  A: 

Given the nature of most PHP pages -- that is, the process runs for a webpage and is thrown away at completion -- I rather doubt this is a problem. I haven't seen problems with circular references before and have used them without problems. In my experience, you will run into more problems with mere memory consumption but PHP 5 has mitigated that somewhat by shifting away from just copying objects and arrays unless told otherwise.

staticsan
+1  A: 

Point by point:

  • If my tree consists of only a few nodes, say 25, is this a problem?

Not unless your nodes are real monsters.

  • Will the memory be freed at the end of the script or am I slowly creating a problem for the server?

When the interpreter shuts down all the memory is released.

  • Under what circumstances will this problem have an effect during script execution?

I doubt you will have anything to worry about unless you have very low memory limits or very large dynamic data structures. If you have 25 nodes that aren't being created/freed frequently you won't have an issue.

  • Will manually destroying the references solve the problem and should I always do it?

It will help. When loading a large data set into our database with Propel we ran into a lot of problem with memory consumption that we tracked to circular references not being freed. Our solution was to call a method that cleared all references.

sig11
+1  A: 

PHP 5.3 will include circular reference detection and destruction features. It's an optional setting, and it should only be used when necessary because the garbage collector will take a performance hit, but it's tailor made for your example.

Develop now, take precaution to explicitly dereference in a __destruct() method, and upgrade to 5.3 when possible.

Encoderer
As far as I remember (before php5.3) __destruct is only called when there are no references to the object left. Therefore __destruct would have to be explicitly called if it's part of a circular reference.
dsas