Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does PHP's 'unset' construct work internally?

Preface: I do know how 'unset' works in the userland, but I would like to find out how it works internally.

When unset is called on zval structure, it decreases the reference counter (refcount__gc). When refcount__gc reaches 0, the variable is no longer used and can be deleted. The question is whether it's always done immediately, or in some cases it can be done later by garbage collector?

I have found two contradictory statements on this:

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. - Stackoverflow answer mentioning 2009 php.net documentation

And the opposite:

When the refcount hits zero, the zval is destroyed and any memory that it was holding is now free - Better Understanding PHP’s Garbage Collection, 2012 article

So which one is correct as of let's say PHP 5.3 and PHP 5.5? If possible, maybe you can provide a link to the unset definition in the PHP source code. Thank you!

like image 636
itsmeee Avatar asked Jul 03 '14 15:07

itsmeee


People also ask

What does the unset () function do?

The function unset() destroys the specified variables. The behavior of unset() inside of a function can vary depending on what type of variable you are attempting to destroy. If a globalized variable is unset() inside of a function, only the local variable is destroyed.

What's better at freeing memory with PHP unset () or $var Null?

null variable: It speedily frees the memory.

What is the use of isset () and unset ()?

Determine if a variable is considered set, this means if a variable is declared and is different than null . If a variable has been unset with the unset() function, it is no longer considered to be set. isset() will return false when checking a variable that has been assigned to null .

How do you unset multiple values in PHP?

You have to use for loop for this. you can use foreach loop but it will not unset all variable one variable still remains.


1 Answers

TL;DR

Both statements are true.

Let me explain. (It's true since at least PHP 5.0 (before, I don't know). There comes phpng now, which does fundamental changes, but this principle is still used.)


The cirular garbage collector

The circular garbage collector is just used for circular references. We have them usually when two objects contain references to each other.

As in this case the refcount__gc would never drop to zero… there's still some reference elsewhere, the normal ZEND_UNSET_* (where the asterisk is either ARRAY, OBJ or VAR) cannot unset it. So it has to wait for the garbage collector.

And the garbage collector is only called periodically for performance reasons.

php-src definitions

You asked for the definition of the ZEND_UNSET_VAR? http://lxr.php.net/xref/PHP_5_6/Zend/zend_vm_def.h#4069

And here is the main function for decrementing refcount etc.: http://lxr.php.net/xref/PHP_5_6/Zend/zend_execute.h#74

Which one is correct?

So, if refcount is zero, we are sure that nothing links to it and we can free it. (Second statement: is just talking about the refcount == 0 case)

But, if it's not zero, we mark the variable as to be checked by the circular garbage collector later. (First statement: not necessarily immediately freed)

like image 73
bwoebi Avatar answered Oct 11 '22 18:10

bwoebi