unset和= null之间的区别

时间:2021-04-23 20:10:51

From a random php.net post:

从一个随机的php.net帖子:

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.

如果你正在做$ whatever = null;那么你正在重写变量的数据。您可能会更快地释放/缩小内存,但它可能会更快地从真正需要它们的代码中窃取CPU周期,从而导致更长的总体执行时间。

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;呢?如上所述,答案和说法一样有用

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

$ whatever = null重置缓冲区和L1缓存,而unset清除缓冲区并重置L2缓存。

Techno mumbo jumbo doesn't constitute an answer.

Techno mumbo jumbo并不构成答案。

5 个解决方案

#1


48  

An important difference between both methods is that unset($a) also removes $a from the symbol table; for example:

两种方法之间的一个重要区别是unset($ a)也会从符号表中删除$ a;例如:

$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 = null时:

$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.

我也通过基准测试运行代码,发现$ a = null比unset()对应程序快6%左右。似乎更新符号表条目比删除它更快。

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.

当使用unset()时,只返回64字节的内存,而$ a = null;释放除272字节内存以外的所有内存。我没有足够的知识来知道为什么两种方法之间存在208字节的差异,但它仍然存在差异。

#2


5  

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

使用未设置时,内存使用和处理时间较少。

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

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

#3


4  

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

在1.95中运行并使用233.29内存

And this

和这个

for($i = 10000000; $i > 0; --$i){
    $cat = new Cat;
    unset($cat);
}

Run in 2.28 and use 233.1 memory

在2.28中运行并使用233.1内存

For what is worth it seem the null method run faster.

值得一提的是,null方法运行速度更快。

#4


1  

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:

10次​​:

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.

看起来null赋值的处理时间更少。

#5


0  

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".

上面的答案很棒,特别是评论“两种方法之间的重要区别是未设置($ a)也从符号表中删除$ a”。

However, I don't think anyone has really fully answered the question 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 more immediately despite PHP self managing memory /garbage collection.

尽管PHP自我管理内存/垃圾回收,但是立即回收内存。

unset()

未设置()

reclaims memory as well but it's more of a "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?

什么时候应该使用null vs unset?

It depends on your speed and data needs, for example, reading a large array from memcache/or DB just to take a part of the data and place into another much smaller subset array may be a good candidate for null because otherwise you may end up keeping all that other data until the function is complete which could build up and cause 500 errors for your web app. Note: in this scenario you would want to do one or the other no matter what. Unset should be preferred when speed is important (when isn't it I suppose) and there is little concern for memory build up.

这取决于你的速度和数据需求,例如,从memcache /或DB读取一个大数组只是为了获取一部分数据并放入另一个更小的子集数组可能是null的一个很好的候选者,否则你可能会结束保留所有其他数据,直到功能完成,这可能会累积并导致您的Web应用程序出现500错误。注意:在这种情况下,无论如何,您都希望做一个或另一个。当速度很重要时(如果不是我想的那样),应该首选取消设置,并且几乎不关心内存的积累。

Example: Taking a large array and placing it into MemCache:

示例:获取一个大型数组并将其放入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;
            }

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.

for循环正在清理数据,可以使用null或unset,但由于它是一个大型数据集,因此可能优先使用null,因为它会更快地回收内存。

#1


48  

An important difference between both methods is that unset($a) also removes $a from the symbol table; for example:

两种方法之间的一个重要区别是unset($ a)也会从符号表中删除$ a;例如:

$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 = null时:

$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.

我也通过基准测试运行代码,发现$ a = null比unset()对应程序快6%左右。似乎更新符号表条目比删除它更快。

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.

当使用unset()时,只返回64字节的内存,而$ a = null;释放除272字节内存以外的所有内存。我没有足够的知识来知道为什么两种方法之间存在208字节的差异,但它仍然存在差异。

#2


5  

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

使用未设置时,内存使用和处理时间较少。

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

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

#3


4  

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

在1.95中运行并使用233.29内存

And this

和这个

for($i = 10000000; $i > 0; --$i){
    $cat = new Cat;
    unset($cat);
}

Run in 2.28 and use 233.1 memory

在2.28中运行并使用233.1内存

For what is worth it seem the null method run faster.

值得一提的是,null方法运行速度更快。

#4


1  

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:

10次​​:

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.

看起来null赋值的处理时间更少。

#5


0  

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".

上面的答案很棒,特别是评论“两种方法之间的重要区别是未设置($ a)也从符号表中删除$ a”。

However, I don't think anyone has really fully answered the question 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 more immediately despite PHP self managing memory /garbage collection.

尽管PHP自我管理内存/垃圾回收,但是立即回收内存。

unset()

未设置()

reclaims memory as well but it's more of a "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?

什么时候应该使用null vs unset?

It depends on your speed and data needs, for example, reading a large array from memcache/or DB just to take a part of the data and place into another much smaller subset array may be a good candidate for null because otherwise you may end up keeping all that other data until the function is complete which could build up and cause 500 errors for your web app. Note: in this scenario you would want to do one or the other no matter what. Unset should be preferred when speed is important (when isn't it I suppose) and there is little concern for memory build up.

这取决于你的速度和数据需求,例如,从memcache /或DB读取一个大数组只是为了获取一部分数据并放入另一个更小的子集数组可能是null的一个很好的候选者,否则你可能会结束保留所有其他数据,直到功能完成,这可能会累积并导致您的Web应用程序出现500错误。注意:在这种情况下,无论如何,您都希望做一个或另一个。当速度很重要时(如果不是我想的那样),应该首选取消设置,并且几乎不关心内存的积累。

Example: Taking a large array and placing it into MemCache:

示例:获取一个大型数组并将其放入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;
            }

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.

for循环正在清理数据,可以使用null或unset,但由于它是一个大型数据集,因此可能优先使用null,因为它会更快地回收内存。