Home » Php » php – the difference between unset and = null

php – the difference between unset and = null

Posted by: admin April 23, 2020 Leave a comment

Questions:

From a random php.net post:

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.

Apparently this is the undisputed truth so maybe someone would be so kind as to explain.

I mean, what, does unset magically not execute any assembly instructions whereas $whatever = null; does? The answer, as given, is about as useful as saying

$whatever = null resets the buffer and the L1 cache whereas unset clears the buffer and resets the L2 cache.

Techno mumbo jumbo doesn’t constitute an answer.

How to&Answers:

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.

Answer:

When using unset, memory usage and processing time is less.

http://php.net/manual/en/function.unset.php#105980

Answer:

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.

Answer:

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.

Answer:

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.