我意识到第二种方法避免了函数调用的开销(更新,实际上是一种语言构造),但知道其中一种方法是否比另一种更好会很有趣。我的大部分代码都使用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
echo "<hr>First:<br>";
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
echo "<hr>Unset:<br>";
unset($x);
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
echo "<hr>Null:<br>";
$x=null;
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
echo "<hr>function:<br>";
function test() {
$x = str_repeat('x', 80000);
}
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
echo "<hr>Reasign:<br>";
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";
echo memory_get_peak_usage() . "<br>\n";
它返回
First:
438296
438352
Unset:
438296
438352
Null:
438296
438352
function:
438296
438352
Reasign:
438296
520216 <-- double usage.
结论,空内存和未设置空闲内存都是预期的(不仅在执行结束时)。另外,对变量重新赋值会在某个点上将值保存两次(520216对438352)
它对数组元素有影响。
考虑这个例子
$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
$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";
?>
根据这一点,“= 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 /示例#1中给出的microtime_float示例。
在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);
...