1

I'm trying to understand how unset() works with classes and their properties. I wrote a little test to see memory usage.

class B {}
class A {
    private $b;
    public function __construct() {
        $this->b = new B;
    }
    public function __destruct() {
        unset($this->b);
    }
}

echo memory_get_usage() . '<br/>';

$a = [];
for ($i = 0; $i < 5000; $i++) {
    $a[$i] = new A;
}

echo memory_get_usage() . '<br/>';

for ($i = 0; $i < 5000; $i++) {
    $a[$i]->__destruct();
    unset($a[$i]);
}
unset($a);

echo memory_get_usage() . '<br/>';

What I was expecting is that the last memory usage should be similar to the first. But it's a lot higher:

236184 (before)
2845320 (peak)
1219432 (after)

I don't really understand how all this works. Thanks for your help!

Note: I tried to use an other name for __destruct (we never know) but that doesn't change anything.

Following some comments below, I tried with memory_get_usage(true); and the result is this:

262144 (before)
3145728 (peak)
2359296 (after)
4
  • 2
    PHP's memory usage is not deterministic like this. Commented Dec 19, 2013 at 10:30
  • 2
    PHP occasionally runs garbage collection, the keyword here being occasionally. Not all unused memory is freed immediately. Commented Dec 19, 2013 at 10:34
  • 2
    Take a look at the description of memory_get_usage(), then look at using the real_usage argument Commented Dec 19, 2013 at 10:34
  • Thanks Mark, I tried with real_usage argument and the result is way more interesting, in the way that less usage is freed. Commented Dec 19, 2013 at 10:51

1 Answer 1

2

IN PHP unset() does just what it's name says - unset a variable. It does not force immediate memory freeing. PHP's garbage collector will do it when it see fits - by intention as soon, as those CPU cycles aren't needed anyway, or as late as before the script would run out of memory, whatever occurs first.

If you are doing $whatever = null; then you are rewriting variable's data. You might get memory freed / shrunk faster, but it may steal CPU cycles from the code that truly needs them sooner, resulting in a longer overall execution time.

Note that until php5.3, if you have two objects in circular reference, such as in a parent-child relationship, calling unset() on the parent object will not free the memory used for the parent reference in the child object. (Nor will the memory be freed when the parent object is garbage-collected.) bug 33595

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.