the difference between unset and = null
Solution 1:
An important difference between both methods is that unset($a)
also removes $a
from the symbol table; for example:
$a = str_repeat('hello world ', 100);
unset($a);
var_dump($a);
Outputs:
Notice: Undefined variable: a in xxx
NULL
But when $a = null
is used:
$a = str_repeat('hello world ', 100);
$a = null;
var_dump($a);
Outputs:
NULL
I ran the code through a benchmark as well and found that $a = null
is roughly 6% faster than its unset()
counterpart. It seems that updating a symbol table entry is faster than removing it.
Addendum
The other difference (as seen in this small script) seems to be how much memory is restored after each call:
echo memory_get_usage(), PHP_EOL;
$a = str_repeat('hello world ', 100);
echo memory_get_usage(), PHP_EOL;
// EITHER unset($a); OR $a = null;
echo memory_get_usage(), PHP_EOL;
When using unset()
all but 64 bytes of memory are given back, whereas $a = null;
frees all but 272 bytes of memory. I don't have enough knowledge to know why there's a 208 bytes difference between both methods, but it's a difference nonetheless.
Solution 2:
When using unset, memory usage and processing time is less.
http://php.net/manual/en/function.unset.php#105980
Solution 3:
I made a simple test.
Considering a simple class like this:
class Cat{
public $eyes = 2;
public $claws = 4;
public $name = "Kitty";
public $sound = ['Meow', 'Miaou'];
}
I run this code code
$start = microtime(true);
for($i = 10000000; $i > 0; --$i){
$cat = new Cat;
$cat = null;
}
$end = microtime(true);
printf("Run in %s and use %s memory",
round($end - $start, 2), round(memory_get_usage() / 1000, 2));
Run in 1.95 and use 233.29 memory
And this
for($i = 10000000; $i > 0; --$i){
$cat = new Cat;
unset($cat);
}
Run in 2.28 and use 233.1 memory
For what is worth it seem the null
method run faster.
Solution 4:
The answers above are great, especially the comment that "An important difference between both methods is that unset($a) also removes $a from the symbol table".
However, I don't think anyone has really fully answered the question in a practical sense because they don't describe how the two are used. OK I think we know that they both basically do the same thing. Why use one over the other?
null
Reclaims memory immediately (at the expense taking longer) despite PHP self managing memory /garbage collection.
unset()
Is usually recommended as it reclaims memory "when I can get to it" and is therefore considered faster as it doesn't dedicate resources immediately to it.
When should use null vs unset?
Basic (small data) data arrays etc. are good candidates for unset because memory won't become an issue. Larger data sets and/or anywhere the need to reclaim memory immediately is better for null. For example such large database requests can cannibalize your PHP memory ceiling very quickly if called multiple times in a function etc. which will cause page 500 errors from memory being full etc.. Therefore, unset should be preferred when speed is important (or in general) and when there is little concern for memory build up.
Example: Taking a large array and placing it into MemCache:
list($inv1, $inv2, $inv3, $inv4) = array_chunk($inventory_array),
ceil(count($val['inventory']) / 4));
MemCache::set($cacheKeyInv1, $inv1, $expiry);
MemCache::set($cacheKeyInv2, $inv2, $expiry);
MemCache::set($cacheKeyInv3, $inv3, $expiry);
MemCache::set($cacheKeyInv4, $inv4, $expiry);
for ($i = 1; $i < 5; $i++) {
${"inv" . $i} = null; // why not use unset ?
}
The for loop is cleaning up the data, null or unset could be used, but since it is a large dataset, perhaps null is preferred as it will reclaim the memory quicker.
Solution 5:
Using the code
$a = str_repeat('hello world ', 10000);
$start1 = microtime(true);
unset($a);
$stop1 = microtime(true);
$a = str_repeat('hello world ', 10000);
$start2 = microtime(true);
$a = null;
$stop2 = microtime(true);
echo 'unset time lap of '. ( $stop1 - $start1 ) .'<br>';
echo 'null time lap of '. ( $stop2 - $start2 ) .'<br>';
for 10 times:
unset time lap of 5.0067901611328E-6
null time lap of 1.1920928955078E-6
unset time lap of 9.5367431640625E-7
null time lap of 9.5367431640625E-7
unset time lap of 0
null time lap of 9.5367431640625E-7
unset time lap of 2.1457672119141E-6
null time lap of 1.1920928955078E-6
unset time lap of 2.1457672119141E-6
null time lap of 0
unset time lap of 9.5367431640625E-7
null time lap of 0
unset time lap of 1.9073486328125E-6
null time lap of 9.5367431640625E-7
unset time lap of 9.5367431640625E-7
null time lap of 0
unset time lap of 1.9073486328125E-6
null time lap of 9.5367431640625E-7
unset time lap of 0
null time lap of 0
Looks like null assignment has less processing time more often.