我意识到第二个避免了函数调用的开销(更新,实际上是一种语言结构),但知道一个是否比另一个更好会很有趣.我一直在使用unset()
我的大部分编码,但我最近查看了一些在网上发现的可敬的类,$var = null
而不是使用它.
有没有首选,是什么原因?
它在2009年的未设置手册页面中提到:
unset()
正如它的名字所说的那样 - 取消变量.它不会强制立即释放内存.PHP的垃圾收集器会在看到拟合时执行它 - 尽快意图,因为无论如何都不需要那些CPU周期,或者在脚本耗尽内存之前,无论先发生什么.如果你这样做,
$whatever = null;
那么你正在重写变量的数据.您可能会更快地释放/缩小内存,但它可能会更快地从真正需要它们的代码中窃取CPU周期,从而导致更长的总体执行时间.
(自2013年起,该unset
手册页不再包含该部分)
请注意,在php5.3之前,如果循环引用中有两个对象,例如在父子关系中,则在父对象上调用unset()将不会释放用于子对象中父引用的内存.(当父对象被垃圾收集时,也不会释放内存.)(bug 33595)
问题" unset和= null之间的区别 "详细说明了一些差异:
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);
Outputs:
NULL
它似乎
$a = null
比它的unset()
对应物快一点:更新符号表条目似乎比删除它更快.
当您尝试使用不存在的(unset
)变量时,将触发错误,并且变量表达式的值将为null.(因为,PHP应该做什么?每个表达式都需要产生一些价值.)
赋值为null的变量仍然是一个完全正常的变量.
unset
实际上不是一个函数,而是一个语言结构.这是不超过一个函数调用return
或include
.
除了性能问题,使用unset
使您的代码的意图更加清晰.
通过对变量执行unset(),您基本上将变量标记为'垃圾收集'(PHP实际上没有一个,但是例如,为了这个原因),因此内存不会立即可用.变量不再容纳数据,但堆栈仍保持较大的大小.执行null方法会丢弃数据并几乎立即缩小堆栈内存.
这来自个人经验和其他人.请在此处查看unset()函数的注释.
我个人在循环中的迭代之间使用unset(),这样我就不必让堆栈的延迟大小合适了.数据消失了,但足迹仍然存在.在下一次迭代中,内存已经被php占用,因此,更快地初始化下一个变量.
看来,"= null"似乎更快.
PHP 5.4结果:
花了0.88389301300049秒
花了2.1757180690765秒
PHP 5.3结果:
花了1.7235369682312秒
花了2.9490959644318秒
PHP 5.2结果:
花了3.0069220066071秒
花了4.7002630233765秒
PHP 5.1结果:
花了2.6272349357605秒
花了5.0403649806976秒
PHP 5.0和4.4开始有所不同.
5.0:
花了10.038941144943秒
花了7.0874409675598秒
4.4:
花了7.5352551937103秒
花了6.6245851516724秒
请记住microtime(true)在PHP 4.4中不起作用所以我不得不使用php.net/microtime/Example#1中给出的microtime_float示例.
它与数组元素有所不同.
考虑这个例子
$a = array('test' => 1); $a['test'] = NULL; echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
在这里,关键'测试'仍然存在.但是,在这个例子中
$a = array('test' => 1); unset($a['test']); echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
钥匙不再存在.
对于通过引用复制的变量,它以不同的方式工作:
$a = 5; $b = &$a; unset($b); // just say $b should not point to any variable print $a; // 5 $a = 5; $b = &$a; $b = null; // rewrites value of $b (and $a) print $a; // nothing, because $a = null
关于对象,特别是在延迟加载场景中,应该考虑垃圾收集器在空闲的CPU周期中运行,所以假设你在很多对象加载时遇到麻烦,小的时间惩罚将解决内存释放问题.
使用time_nanosleep使GC能够收集内存.将变量设置为null是可取的.
在生产服务器上测试,最初工作消耗50MB然后停止.使用nanosleep后,14MB是恒定的内存消耗.
应该说这取决于GC行为,可能会从PHP版本变为版本.但它适用于PHP 5.3.
例如.此示例(代码来自VirtueMart2 google feed)
for($n=0; $n" . memory_get_usage() . "";//$ids[$n]; time_nanosleep(0, 10000000); } $product = $productModel->getProductSingle((int)$ids[$n],true, true, true); ...