我意识到第二种方法避免了函数调用的开销(更新,实际上是一种语言构造),但知道其中一种方法是否比另一种更好会很有趣。我的大部分代码都使用unset(),但最近我在网上找到了一些使用$var = null的体面类。
是否有一个首选的,理由是什么?
我意识到第二种方法避免了函数调用的开销(更新,实际上是一种语言构造),但知道其中一种方法是否比另一种更好会很有趣。我的大部分代码都使用unset(),但最近我在网上找到了一些使用$var = null的体面类。
是否有一个首选的,理由是什么?
当前回答
它对数组元素有影响。
考虑这个例子
$a = array('test' => 1);
$a['test'] = NULL;
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
这里,键“test”仍然存在。然而,在这个例子中
$a = array('test' => 1);
unset($a['test']);
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
密钥不再存在。
其他回答
PHP 7已经着手解决这类内存管理问题,并将其使用减少到最小。
<?php
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
$a = 'a';
$a = NULL;
}
$elapsed = microtime(true) - $start;
echo "took $elapsed seconds\r\n";
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
$a = 'a';
unset($a);
}
$elapsed = microtime(true) - $start;
echo "took $elapsed seconds\r\n";
?>
PHP 7.1输出:
花了0.16778993606567秒 花了0.16630101203918秒
通过对变量执行unset()操作,您实际上已经将变量标记为“垃圾收集”(PHP实际上并没有这样的功能,但为了举例说明),因此内存不能立即可用。该变量不再存储数据,但堆栈仍然保持较大的大小。执行null方法几乎会立即丢弃数据并缩小堆栈内存。
这是我个人的经验,也是别人的经验。在这里查看unset()函数的注释。
我个人在循环的迭代之间使用unset(),这样我就不必在大小上有堆栈的延迟。数据消失了,但足迹还在。在下一次迭代时,内存已经被php占用,因此可以更快地初始化下一个变量。
在2009年的unset手册页面中提到:
unset() does just what its name says - unset a variable. It does not force immediate memory freeing. PHP's garbage collector will do it when it see fits - by intention as soon, as those CPU cycles aren't needed anyway, or as late as before the script would run out of memory, whatever occurs first. 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.
(自2013年起,未设置的手册页不再包括该部分)
注意,在php5.3之前,如果循环引用中有两个对象,例如在父子关系中,在父对象上调用unset()将不会释放用于子对象中父引用的内存。当父对象被垃圾回收时,内存也不会被释放。
问题“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);
输出:
NULL
$a = null似乎比它的unset()对手快一点:更新符号表项似乎比删除它快。
当您尝试使用不存在(未设置)变量时,将触发一个错误,变量表达式的值将为null。(因为,PHP还应该做什么?每个表达式都需要产生某个值。) 一个赋值为null的变量仍然是一个完全正常的变量。
对于对象,特别是在惰性加载场景中,应该考虑垃圾收集器运行在空闲的CPU周期中,因此假设您遇到了麻烦,当大量对象加载时,小时间惩罚将解决内存释放问题。
使用time_nanosleep使GC能够收集内存。 将变量设置为null是可取的。
在生产服务器上测试,最初作业消耗50MB,然后停止。 在使用nanosleep之后,14MB的内存消耗是不变的。
有人会说,这取决于GC行为,而GC行为可能会随着PHP版本的不同而变化。 但它在PHP 5.3上运行良好。
如。此示例(代码取自VirtueMart2谷歌提要)
for($n=0; $n<count($ids); $n++)
{
//unset($product); //usefull for arrays
$product = null
if( $n % 50 == 0 )
{
// let GC do the memory job
//echo "<mem>" . memory_get_usage() . "</mem>";//$ids[$n];
time_nanosleep(0, 10000000);
}
$product = $productModel->getProductSingle((int)$ids[$n],true, true, true);
...
它对数组元素有影响。
考虑这个例子
$a = array('test' => 1);
$a['test'] = NULL;
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
这里,键“test”仍然存在。然而,在这个例子中
$a = array('test' => 1);
unset($a['test']);
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";
密钥不再存在。