52

从一个随机的 php.net 帖子

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

显然这是无可争议的事实,所以也许有人会这么好心解释一下。

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

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

Techno mumbo jumbo 不构成答案。

4

6 回答 6

73

两种方法之间的一个重要区别是它也从符号表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比对应的代码快大约 6% unset()。似乎更新符号表条目比删除它更快。

附录

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

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 字节的差异,但它仍然存在差异。

于 2012-12-02T08:41:54.420 回答
8

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

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

于 2012-12-02T07:58:36.843 回答
6

我做了一个简单的测试。

考虑这样一个简单的类:

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方法运行得更快。

于 2017-06-01T13:03:38.993 回答
6

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

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

无效的

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

未设置()

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

什么时候应该使用 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 是首选,因为它会更快地回收内存。

于 2018-06-19T14:38:27.340 回答
1

使用代码

$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

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

于 2016-02-11T00:58:31.103 回答
0

不同之处在于 null 的赋值是 null 的赋值,而不是未初始化。如果你不处理性能关键问题,你关闭使用 unset,如果你在你的 PHP 版本上测试这两种可能性。主要区别在于 PHP 7.4 和属性类型,您可以取消设置不可为空的属性,但不能分配 null。

class C {
    public int $value;
}

$c = new C();
var_dump(isset($c->value));   // false
$c->value = 5;
var_dump($c->value);          //5
unset($c->value);
//var_dump($c->value);       //Error: Typed property C::$value must not be accessed before initialization
var_dump(isset($c->value));  // false
$c->value = 5;
$c->value = null;            //Error Typed property C::$value must be int, null used

https://3v4l.org/VUVD1

于 2022-02-08T21:27:10.153 回答