【问题标题】:the difference between unset and = nullunset 和 = null 的区别
【发布时间】:2012-11-19 23:13:27
【问题描述】:

来自random php.net post

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

显然这是undisputed truth,所以也许有人会好心解释一下。

我的意思是,unset 神奇地不执行任何汇编指令,而$whatever = null; 执行?给出的答案和说的一样有用

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

Techno mumbo jumbo 不构成答案。

【问题讨论】:

  • 我认为它可能与作为 PHP 中的值的变量有关(是的,我说过:内部变量 对象)。所以在清理方面可能“设置变量的值(为空)”和“删除变量”之间存在差异......但这只是我的疯狂猜测;)
  • 你让它变得比现在复杂得多。分配 var null 意味着该变量设置为 null 值。取消设置使 var 不存在。
  • @itachi 它可能是答案,..还有更多解释

标签: php


【解决方案1】:

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

$a = str_repeat('hello world ', 100);
unset($a);
var_dump($a);

输出:

Notice: Undefined variable: a in xxx
NULL

但是当使用$a = null 时:

$a = str_repeat('hello world ', 100);
$a = null;
var_dump($a);

输出:

NULL

我还通过基准测试运行了代码,发现 $a = null 比其对应的 unset() 快大约 6%。似乎更新符号表条目比删除它更快。

附录

另一个区别(如这个小脚本所示)似乎是每次调用后恢复了多少内存:

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;

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

【讨论】:

  • 正如@Ashkan 指出的那样,当您清除许多变量时(> 80-ish,根据the linkunset() 可以比= null 更快并且释放更多内存。
  • @Beetle952580 这很有趣;诚然,我没有测试未设置的变量批次,认为这无关紧要:)
  • @Ja͢ck,这些测试在什么环境上运行?
  • @Pacerier 不确定您所说的“什么环境”是什么意思?
  • @Ja͢ck,服务器和操作系统等
【解决方案2】:

使用 unset 时,内存使用和处理时间更少。

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

【讨论】:

    【解决方案3】:

    我做了一个简单的测试。

    考虑这样一个简单的类:

    class Cat{
        public $eyes  = 2;
        public $claws = 4;
        public $name  = "Kitty";
        public $sound = ['Meow', 'Miaou'];
    }
    

    我运行这段代码

    $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));
    

    在 1.95 中运行并使用 233.29 内存

    还有这个

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

    在 2.28 中运行并使用 233.1 内存

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

    【讨论】:

    • Windows 10+php7.1 32bits: 1.69sec (null) vs 1.71sec (unset),所以它不一样,但它确实是一个微优化。
    • 只是一个注释。您的时间看起来是正确的,但内存使用统计数据可能并未表明您想要什么。每次运行$cat = new Cat; PHP 都会垃圾收集旧猫并回收该内存,无论未设置/为空。所以这只是向你展示最后一次 Cat 实例化的内存使用差异。
    【解决方案4】:

    上面的答案很棒,尤其是“两种方法之间的一个重要区别是 unset($a) 也会从符号表中删除 $a”的评论。

    但是,我认为没有人真正从实际意义上完全回答了这个问题,因为他们没有描述如何使用这两者。好的,我想我们知道他们基本上都做同样的事情。为什么要使用一个而不是另一个?

    尽管 PHP 自我管理内存/垃圾收集,但会立即回收内存(代价是花费更长的时间)。

    unset()

    通常建议使用它,因为它“当我可以使用它时”回收内存,因此被认为更快,因为它不会立即将资源专用于它。

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

    基本(小数据)数据数组等非常适合unset,因为内存不会成为问题。 null 更适合较大的数据集和/或需要立即回收内存的任何地方。例如,如果在一个函数等中多次调用此类大型数据库请求,可能会非常快速地占用您的 PHP 内存上限,这将导致内存已满等导致页面 500 错误。因此,unset 应该是首选速度很重要(或一般而言),并且几乎不需要担心内存的增加。

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

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

    【讨论】:

      【解决方案5】:

      使用代码

      $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>';
      

      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
      

      看起来空赋值的处理时间更短。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-23
        • 2019-08-23
        • 2010-09-05
        • 1970-01-01
        • 2015-12-06
        • 1970-01-01
        • 2013-01-12
        • 2011-02-14
        相关资源
        最近更新 更多