Is it true that unsetting variables doesn't actually decrease the memory consumption during runtime?
Yep. From PHP.net:
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.
Regarding your other question:
And is there any reason to unset variables apart from destroying session varaibles for instance or for scoping?
Not really, you pretty much summed it.
Answer from Aron Rotteveel on Stack OverflowVideos
Hey all, I'm trying to learn as much as I can about PHP and the best programming practices for it. I never use PHP's unset() function to unset a variable, because I've never learned if I should or not. Is it generally recommended to unset all variables when they are done use? Do you use unset() in your projects?
I currently use a MVC framework (CodeIgniter) so I guess it would depend on the specific variable about where would be the best place to unset them. Some would be unset in the views, some in the controllers, some in the models.
Any insight you may provide would be highly appreciated. :)
EDIT: People in the comments are saying that it can be a good idea for memory usage / efficiency. However, it is my understand that PHP variables automatically cease to exist once the script is done running. So, would it really help at all with memory usage?
Is it true that unsetting variables doesn't actually decrease the memory consumption during runtime?
Yep. From PHP.net:
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.
Regarding your other question:
And is there any reason to unset variables apart from destroying session varaibles for instance or for scoping?
Not really, you pretty much summed it.
PHP will clean up memory on its own with the garbage collector, and it usually does a pretty good job. unsetting will simply make it explicit that you're done with that particular variable.
Let's consider the function:
function foo() {
static $bar;
$bar++;
unset($bar);
}
foo(); //static $bar is 1
foo(); //static $bar is 2
The function compiles to:
function name: foo
number of ops: 11
compiled vars: !0 = $bar
line # * op fetch ext return operands
---------------------------------------------------------------------------------
2 0 > EXT_NOP
4 1 EXT_STMT
2 FETCH_W static $0 'bar'
3 ASSIGN_REF !0, $0
5 4 EXT_STMT
5 POST_INC ~1 !0
6 FREE ~1
6 7 EXT_STMT
8 UNSET_VAR !0
7 9 EXT_STMT
10 > RETURN null
A variable actually exists outside each function call to foo() and, on each call, it's fetched and a reference to it is assigned to $bar. In fact, it's very similar to this:
function foo() {
global $bar;
$bar++;
unset($bar);
}
When you call unset(), you're only destroying the reference you created, not the underlying value.
I didn't confirm, but what I'd guess that happens is this:
- The underlying representation of the variabe (the zval) is stored so that its reference count is 1.
- When
foo()is called, the symbol$baris associated with this zval, its reference count is increased to 2 and the reference flag is set. - When
unsetis called, the zval has its reference count decreased to 1, the reference flag is probably cleared and the symbol$baris removed.
See reference count basics.
Inside a function, variable names referencing static variables are just that.. references. In effect, unset destroys the reference.
As of PHP 5.3, you can assign an anonymous function to a variable, then unset it:
Copy$upper = function($str) {
return strtoupper($str);
};
echo $upper('test1');
// outputs: TEST1
unset($upper);
echo $upper('test2');
// Notice: Undefined variable: upper
// Fatal error: Function name must be a string
Before 5.3, you can do something similar with create_function()
Copy$func = create_function('$arg', 'return strtoupper($arg);');
echo $func('test1');
unset($func);
$func2 = "\0lambda_1";
echo $func2('test2.a'), "\n"; // Same results, this is the "unset" $func function
echo $func('test2.b'); // Fatal Error
runkit_function_remove โ Remove a function definition http://php.net/manual/en/function.runkit-function-remove.php
There are different ways to delete an array element, where some are more useful for some specific tasks than others.
Deleting a Single Array Element
If you want to delete just one single array element you can use unset() and alternatively array_splice().
By key or by value?
If you know the value and don't know the key to delete the element you can use array_search() to get the key.
This only works if the element doesn't occur more than once, since array_search() returns the first hit only.
unset() Expression
Note: When you use unset() the array keys wonโt change.
If you want to reindex the keys you can use array_values() after unset(),
which will convert all keys to numerically enumerated keys starting from 0
(the array remains a list).
Example Code:
$array = [0 => "a", 1 => "b", 2 => "c"];
unset($array[1]);
// โ Key of element to delete
Example Output:
[
[0] => a
[2] => c
]
array_splice() Function
If you use array_splice() the (integer) keys will automatically be reindex-ed,
but the associative (string) keys won't change โ as opposed to array_values() after unset(),
which will convert all keys to numerical keys.
Note: array_splice()
needs the offset, not the key, as the second parameter; offset = array_flip(array_keys(array))[key].
Example Code:
$array = [0 => "a", 1 => "b", 2 => "c"];
array_splice($array, 1, 1);
// โ Offset of element to delete
Example Output:
[
[0] => a
[1] => c
]
array_splice(), same as unset(), take the array by reference. You donโt assign the return values back to the array.
Deleting Multiple Array Elements
If you want to delete multiple array elements and donโt want
to call unset() or array_splice() multiple times you can use the functions array_diff() or
array_diff_key() depending on whether you know the values or the keys of the elements to remove from the array.
array_diff() Function
If you know the values of the array elements which you want to delete, then you can use array_diff().
As before with unset() it wonโt change the keys of the array.
Example Code:
$array = [0 => "a", 1 => "b", 2 => "c", 3 => "c"];
$array = array_diff($array, ["a", "c"]);
// โโโโโโโโโโ
// Array values to delete
Example Output:
[
[1] => b
]
array_diff_key() Function
If you know the keys of the elements which you want to delete, then you want to use array_diff_key().
You have to make sure you pass the keys as keys in the second parameter and not as values.
Keys wonโt reindex.
Example Code:
$array = [0 => "a", 1 => "b", 2 => "c"];
$array = array_diff_key($array, [0 => "xy", "2" => "xy"]);
// โ โ
// Array keys of elements to delete
Example Output:
[
[1] => b
]
If you want to use unset() or array_splice() to delete multiple elements with the same value you can use
array_keys() to get all the keys for a specific value
and then delete all elements.
array_filter() Function
If you want to delete all elements with a specific value in the array you can use array_filter().
Example Code:
$array = [0 => "a", 1 => "b", 2 => "c"];
$array = array_filter($array, static function ($element) {
return $element !== "b";
// โ
// Array value which you want to delete
});
Example Output:
[
[0] => a
[2] => c
]
It should be noted that unset() will keep indexes untouched, which is what you'd expect when using string indexes (array as hashtable), but can be quite surprising when dealing with integer indexed arrays:
$array = array(0, 1, 2, 3);
unset($array[2]);
var_dump($array);
/* array(3) {
[0]=>
int(0)
[1]=>
int(1)
[3]=>
int(3)
} */
$array = array(0, 1, 2, 3);
array_splice($array, 2, 1);
var_dump($array);
/* array(3) {
[0]=>
int(0)
[1]=>
int(1)
[2]=>
int(3)
} */
So array_splice() can be used if you'd like to normalize your integer keys. Another option is using array_values() after unset():
$array = array(0, 1, 2, 3);
unset($array[2]);
$array = array_values($array);
var_dump($array);
/* array(3) {
[0]=>
int(0)
[1]=>
int(1)
[2]=>
int(3)
} */