我意识到第二种方法避免了函数调用的开销(更新,实际上是一种语言构造),但知道其中一种方法是否比另一种更好会很有趣。我的大部分代码都使用unset(),但最近我在网上找到了一些使用$var = null的体面类。

是否有一个首选的,理由是什么?


当前回答

郑重声明,不包括花费的时间:

<?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)

其他回答

对于对象,特别是在惰性加载场景中,应该考虑垃圾收集器运行在空闲的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);
    ...

来自注释的代码示例

echo "PHP Version: " . phpversion() . PHP_EOL . PHP_EOL;

$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    $a = 'a';
    $a = NULL;
}
$elapsed = microtime(true) - $start;

echo "took $elapsed seconds" . PHP_EOL;



$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    $a = 'a';
    unset($a);
}
$elapsed = microtime(true) - $start;

echo "took $elapsed seconds" . PHP_EOL;

在docker容器中运行image php:7.4-fpm等。

PHP Version: 7.4.8
took 0.22569918632507 seconds null
took 0.11705803871155 seconds unset
took 0.20791196823121 seconds null
took 0.11697316169739 seconds unset

PHP Version: 7.3.20
took 0.22086310386658 seconds null
took 0.11882591247559 seconds unset
took 0.21383500099182 seconds null
took 0.11916995048523 seconds unset

PHP Version: 7.2.32
took 0.24728178977966 seconds null
took 0.12719893455505 seconds unset
took 0.23839902877808 seconds null
took 0.12744522094727 seconds unset

PHP Version: 7.1.33
took 0.51380109786987 seconds null
took 0.50135898590088 seconds unset
took 0.50358104705811 seconds null
took 0.50115609169006 seconds unset

PHP Version: 7.0.33
took 0.50918698310852 seconds null
took 0.50490307807922 seconds unset
took 0.50227618217468 seconds null
took 0.50514912605286 seconds unset

PHP Version: 5.6.40
took 1.0063569545746 seconds null
took 1.6303179264069 seconds unset
took 1.0689589977264 seconds null
took 1.6382601261139 seconds unset

PHP Version: 5.4.45
took 1.0791940689087 seconds null
took 1.6308979988098 seconds unset
took 1.0029168128967 seconds null
took 1.6320278644562 seconds unset

但是,再举一个例子:

<?php
ini_set("memory_limit", "512M");

echo "PHP Version: " . phpversion() . PHP_EOL . PHP_EOL;

$start = microtime(true);
$arr = [];
for ($i = 0; $i < 1000000; $i++) {
    $arr[] = 'a';
}
$arr = null;
$elapsed = microtime(true) - $start;

echo "took $elapsed seconds" . PHP_EOL;



$start = microtime(true);
$arr = [];
for ($i = 0; $i < 1000000; $i++) {
    $arr[] = 'a';
}
unset($arr);
$elapsed = microtime(true) - $start;

echo "took $elapsed seconds" . PHP_EOL;

结果:

PHP Version: 7.4.8
took 0.053696155548096 seconds
took 0.053897857666016 seconds

PHP Version: 7.3.20
took 0.054572820663452 seconds
took 0.054342031478882 seconds

PHP Version: 7.2.32
took 0.05678391456604 seconds
took 0.057311058044434 seconds


PHP Version: 7.1.33
took 0.097366094589233 seconds
took 0.073100090026855 seconds

PHP Version: 7.0.33
took 0.076443910598755 seconds
took 0.077098846435547 seconds

PHP Version: 7.0.33
took 0.075634002685547 seconds
took 0.075317859649658 seconds

PHP Version: 5.6.40
took 0.29681086540222 seconds
took 0.28199100494385 seconds

PHP Version: 5.4.45
took 0.30513095855713 seconds
took 0.29265689849854 seconds

如果没有释放即时内存,则取消设置代码仍然是非常有用的,并且每次在退出方法之前传递代码步骤时都这样做是一个很好的实践。请注意,这不是关于释放即时内存。 直接内存是CPU的,辅助内存是RAM。

这也解决了防止内存泄漏的问题。

请参阅此链接 http://www.hackingwithphp.com/18/1/11/be-wary-of-garbage-collection-part-2

我使用unset已经很长时间了。

更好的做法是在代码中立即取消所有已经作为数组使用的变量。

$data['tesst']='';
$data['test2']='asdadsa';
....
nth.

只需要unset($data);释放所有变量的使用。

请参阅相关主题取消设置

在PHP中取消变量设置有多重要?

(错误)

郑重声明,不包括花费的时间:

<?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)

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秒