4

Possible Duplicate:
What's better at freeing memory with PHP: unset() or $var = null

As far as the garbage collection goes, is 1 better than the other in any circumstances?

EDIT: Particularly if $var is a very large variable with a lot of levels of recursion and other objects (so to do with recursive cleanup of large objects)

EDIT: Removed this: I can think of only 1 thing, and that's that isset($var) will respond differently in either case.

Because apparently I was mistaken... They both react the same.

Community
  • 1
  • 1
Ricky Cook
  • 951
  • 8
  • 14
  • Why do you need to unset it? What's wrong with automatic doing that as soon as variable is out of scope? – zerkms Aug 02 '12 at 02:10
  • "is a very large variable with a lot of levels of recursion and other objects" -- so? – zerkms Aug 02 '12 at 02:11
  • 1
    It's to do with weak references. The variable never actually goes "out of scope" per se, it just needs to be cleaned up when it becomes invalid. – Ricky Cook Aug 02 '12 at 02:11
  • There is no weak references in php, isn't there? – zerkms Aug 02 '12 at 02:11
  • 1
    http://php.net/manual/en/book.weakref.php – Ricky Cook Aug 02 '12 at 02:12
  • 1
    It's a fantastic addition... Highly needed for high performance apps. – Ricky Cook Aug 02 '12 at 02:12
  • ok, it is extension. But back to the question: why do you need to unset the variable? Is there any issues with memory amount required by script? Is your script a "daemon"-like (the one that works continuously)? – zerkms Aug 02 '12 at 02:13
  • 1
    No, but it provides a cache-like function. Basically, you load a whoooooole lot (millions) of objects, and you keep cache the most important using a weak reference... That way, if the variable is in scope somewhere, it keeps the reference in cache. If not, it's free to be collected. I need to delete the reference object when the contained var goes out of scope. – Ricky Cook Aug 02 '12 at 02:15
  • @FuzziBear: reference is removed by php when variable goes out of scope. "if the variable is in scope somewhere" --- there is only one thread in php, so there is no "somewhere" – zerkms Aug 02 '12 at 02:17
  • "and you keep cache the most important using a weak reference" --- if you want your GC to work as normal - don't use weakref extension. As simple as 1-2-3 ;-) – zerkms Aug 02 '12 at 02:19
  • 1
    Whilst there's only 1 thread, you can have a very complex object hierarchy. If you load image data and store it in a class somewhere, you really only want to cache it for as long as it's already in memory (anything else is a waste). Weak references are REALLY important for very large data in very large scale applications. – Ricky Cook Aug 02 '12 at 02:26
  • @Michael: whilst it's similar (and my use case could have been answered by that if I had have found it in my google search), I think there are more subtle differences like the reference and undefined notice behaviours that make this a question in and of itself. – Ricky Cook Aug 02 '12 at 02:36

3 Answers3

4
unset($var);
// You will get Undefined variable Notice.
if ($var) {}

$var = null;
// it's ok.
if ($var) {}

Addition of GC of php.

PHP's Garbage Collection is based on the refcount of the zval, if refcount becomes 0, then the zval can be freed.

So if $a = $b = array(/*a very large array*/);, unset only $a or only $b won't free the memory of the large array.

unset($a); or $a = null or assign another value to $a will all let the refcount decrease by 1, but the memory will be freed only when the refcount decrease to 0.

xdazz
  • 158,678
  • 38
  • 247
  • 274
3

unset does not force immediate memory freeing but leaves it for the gc. $var = null; however forces immediate memory release.

See example:

 // $a = NULL; (better I think)
 $a = 5;
 $b = & $a;
 $a = NULL;
 print "b $b "; // b 
 print(! isset($b)); // 1 
 ?>

It is also worthy to note that in the case of an array unset destroys the variable completely. i.e.:

<?php
$ar = array(1,2,3,4);
var_dump($ar);
echo "<br />";

unset($ar[2]);
var_dump($ar);
echo "<br />";

$ar[1] = null;
var_dump($ar);
?>

Returns the output:

array(4) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) } 
array(3) { [0]=> int(1) [1]=> int(2) [3]=> int(4) } 
array(3) { [0]=> int(1) [1]=> NULL [3]=> int(4) }
rtuner
  • 2,362
  • 3
  • 25
  • 37
  • I wish I could select multiple answers for the solution... Since I can only select 1, this is basically what I was looking for. For future readers, RiaD's and xdazz's answers also give very helpful information for other use cases. Xdazz really went the extra mile with explanation about GC internals ;) – Ricky Cook Aug 02 '12 at 02:32
  • How does that example demonstrate anything about "forcing" the garbage collector?! – deceze Jul 26 '17 at 15:39
2
$a = 5;
$b = &$a;
unset($b); //just say $b should not pointer to any var
print $a; // 5


$a = 5;
$b = &$a;
$b = null;
print $a; // nothing, because $a = null
RiaD
  • 46,822
  • 11
  • 79
  • 123