用 PHP 释放内存有什么好处:unset() 或 $var = null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/584960/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 23:09:39  来源:igfitidea点击:

What's better at freeing memory with PHP: unset() or $var = null

php

提问by alex

I realise the second one avoids the overhead of a function call (update, is actually a language construct), but it would be interesting to know if one is better than the other. I have been using unset()for most of my coding, but I've recently looked through a few respectable classes found off the net that use $var = nullinstead.

我意识到第二个避免了函数调用的开销(update,实际上是一种语言构造),但是知道一个是否比另一个更好会很有趣。我一直在使用unset()我的大部分编码,但我最近查看了一些从网上找到的可敬类,但它们却被使用$var = null

Is there a preferred one, and what is the reasoning?

有没有首选的,理由是什么?

采纳答案by VonC

It was mentioned in the unset manual's page in 2009:

在 2009 年的未设置手册页面中提到了它:

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.

unset()就像它的名字所说的那样 - 取消设置一个变量。它不会强制立即释放内存。PHP 的垃圾收集器会在它认为合适的时候执行它 - 出于意图,因为无论如何都不需要这些 CPU 周期,或者直到脚本耗尽内存之前,无论先发生什么。

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

(Since 2013, that unsetman pagedon't include that section anymore)

(自 2013 年以来,该unset手册页不再包含该部分)

Note that until php5.3, if you have two objects in circular reference, such as in a parent-child relationship, calling unset() on the parent object will not free the memory used for the parent reference in the child object. (Nor will the memory be freed when the parent object is garbage-collected.) (bug 33595)

注意在php5.3之前,如果你有两个循环引用的对象,比如父子关系,在父对象上调用unset()不会释放子对象中父引用使用的内存。(当父对象被垃圾收集时也不会释放内存。)(错误 33595



The question "difference between unset and = null" details some differences:

问题“ unset 和 = null 之间的差异”详细说明了一些差异:



unset($a)also removes $afrom the symbol table; for example:

unset($a)$a从符号表中删除;例如:

$a = str_repeat('hello world ', 100);
unset($a);
var_dump($a);

Outputs:

输出:

Notice: Undefined variable: a in xxx
NULL

But when $a = nullis used:

但是什么时候$a = null使用:

$a = str_repeat('hello world ', 100);
$a = null;
var_dump($a);
Outputs:

NULL

It seems that $a = nullis a bit faster than its unset()counterpart: updating a symbol table entry appears to be faster than removing it.

似乎$a = null比它的unset()对应物快一点:更新符号表条目似乎比删除它更快。



  • when you try to use a non-existent (unset) variable, an error will be triggered and the value for the variable expression will be null. (Because, what else should PHP do? Every expression needs to result in some value.)
  • A variable with null assigned to it is still a perfectly normal variable though.
  • 当您尝试使用不存在的 ( unset) 变量时,将触发错误并且变量表达式的值为空。(因为,PHP 还应该做什么?每个表达式都需要产生某个值。)
  • 尽管如此,分配了 null 的变量仍然是一个完全正常的变量。

回答by Alex Barrett

unsetis not actually a function, but a language construct. It is no more a function call than a returnor an include.

unset实际上不是一个函数,而是一个语言结构。它只不过是一个函数调用,而不是 areturn或 an include

Aside from performance issues, using unsetmakes your code's intentmuch clearer.

除了性能问题之外,使用unset使您的代码意图更加清晰。

回答by William Holroyd

By doing an unset() on a variable, you've essentially marked the variable for 'garbage collection' (PHP doesn't really have one, but for example's sake) so the memory isn't immediately available. The variable no longer houses the data, but the stack remains at the larger size. Doing the null method drops the data and shrinks the stack memory almost immediately.

通过对变量执行 unset() ,您实际上已将变量标记为“垃圾收集”(PHP 并没有真正有一个,但例如为了),因此内存不是立即可用的。该变量不再包含数据,但堆栈保持较大的大小。执行 null 方法几乎立即删除数据并缩小堆栈内存。

This has been from personal experience and others as well. See the comments of the unset() function here.

这是来自个人经验和其他人的经验。在此处查看 unset() 函数的注释。

I personally use unset() between iterations in a loop so that I don't have to have the delay of the stack being yo-yo'd in size. The data is gone, but the footprint remains. On the next iteration, the memory is already being taken by php and thus, quicker to initialize the next variable.

我个人在循环中的迭代之间使用 unset() ,这样我就不必让堆栈的延迟在大小上像悠悠球一样。数据消失了,但足迹仍然存在。在下一次迭代中,内存已经被 php 占用,因此可以更快地初始化下一个变量。

回答by William Holroyd

<?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";
?>

Per that it seems like "= null" is faster.

每一个似乎“= null”更快。

PHP 5.4 results:

PHP 5.4 结果:

  • took 0.88389301300049 seconds
  • took 2.1757180690765 seconds
  • 花了 0.88389301300049 秒
  • 花了 2.1757180690765 秒

PHP 5.3 results:

PHP 5.3 结果:

  • took 1.7235369682312 seconds
  • took 2.9490959644318 seconds
  • 花了 1.7235369682312 秒
  • 花了 2.9490959644318 秒

PHP 5.2 results:

PHP 5.2 结果:

  • took 3.0069220066071 seconds
  • took 4.7002630233765 seconds
  • 花了 3.0069220066071 秒
  • 花了 4.7002630233765 秒

PHP 5.1 results:

PHP 5.1 结果:

  • took 2.6272349357605 seconds
  • took 5.0403649806976 seconds
  • 花了 2.6272349357605 秒
  • 花了 5.0403649806976 秒

Things start to look different with PHP 5.0 and 4.4.

PHP 5.0 和 4.4 的情况开始有所不同。

5.0:

5.0:

  • took 10.038941144943 seconds
  • took 7.0874409675598 seconds
  • 花了 10.038941144943 秒
  • 花了 7.0874409675598 秒

4.4:

4.4:

  • took 7.5352551937103 seconds
  • took 6.6245851516724 seconds
  • 花了 7.5352551937103 秒
  • 耗时 6.6245851516724 秒

Keep in mind microtime(true) doesn't work in PHP 4.4 so I had to use the microtime_float example given in php.net/microtime / Example #1.

请记住 microtime(true) 在 PHP 4.4 中不起作用,所以我不得不使用 php.net/microtime / Example #1 中给出的 microtime_float 示例。

回答by auris

It makes a difference with array elements.

它与数组元素有所不同。

Consider this example

考虑这个例子

$a = array('test' => 1);
$a['test'] = NULL;
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";

Here, the key 'test' still exists. However, in this example

在这里,关键的“测试”仍然存在。然而,在这个例子中

$a = array('test' => 1);
unset($a['test']);
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";

the key no longer exists.

密钥不再存在。

回答by RiaD

It works in a different way for variables copied by reference:

对于通过引用复制的变量,它以不同的方式工作:

$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

回答by OSP

Regarding objects, especially in lazy-load scenario, one should consider garbage collector is running in idle CPU cycles, so presuming you're going into trouble when a lot of objects are loading small time penalty will solve the memory freeing.

关于对象,尤其是在延迟加载的情况下,应该考虑垃圾收集器在空闲的 CPU 周期中运行,因此假设您在加载大量对象时遇到麻烦,时间损失很小,这将解决内存释放问题。

Use time_nanosleep to enable GC to collect memory. Setting variable to null is desirable.

使用 time_nanosleep 开启 GC 收集内存。将变量设置为 null 是可取的。

Tested on production server, originally the job consumed 50MB and then was halted. After nanosleep was used 14MB was constant memory consumption.

在生产服务器上测试,最初该作业消耗了 50MB,然后被暂停。使用 nanosleep 后,14MB 是恒定内存消耗。

One should say this depends on GC behaviour which may change from PHP version to version. But it works on PHP 5.3 fine.

应该说这取决于 GC 行为,这可能会因 PHP 版本而异。但它在 PHP 5.3 上运行良好。

eg. this sample (code taken form VirtueMart2 google feed)

例如。此示例(从 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);
    ...

回答by Anggie Aziz

I still doubt about this, but I've tried it at my script and I'm using xdebug to know how it will affect my app memory usage. The script is set on my function like this :

我仍然对此表示怀疑,但我已经在我的脚本中尝试过,并且我正在使用 xdebug 来了解它将如何影响我的应用程序内存使用。该脚本在我的函数上设置如下:

function gen_table_data($serv, $coorp, $type, $showSql = FALSE, $table = 'ireg_idnts') {
    $sql = "SELECT COUNT(`operator`) `operator` FROM $table WHERE $serv = '$coorp'";
    if($showSql === FALSE) {
        $sql = mysql_query($sql) or die(mysql_error());
        $data = mysql_fetch_array($sql);
        return $data[0];
    } else echo $sql;
}

And I add unset just before the returncode and it give me : 160200 then I try to change it with $sql = NULLand it give me : 160224 :)

我在return代码之前添加了 unset ,它给了我:160200 然后我尝试用$sql = NULL它来改变它,它给了我:160224 :)

But there is something unique on this comparative when I am not using unset() or NULL, xdebug give me 160144 as memory usage

但是当我不使用 unset() 或 NULL 时,这个比较有一些独特之处,xdebug 给我 160144 作为内存使用量

So, I think giving line to use unset() or NULL will add process to your application and it will be better to stay origin with your code and decrease the variable that you are using as effective as you can .

因此,我认为让行使用 unset() 或 NULL 将为您的应用程序添加进程,最好保持代码的原点并尽可能有效地减少您正在使用的变量。

Correct me if I'm wrong, thanks

如果我错了,请纠正我,谢谢

回答by Michael B.

I created a new performance test for unsetand =null, because as mentioned in the comments the here written has an error (the recreating of the elements). I used arrays, as you see it didn't matter now.

我为unsetand创建了一个新的性能测试=null,因为正如评论中提到的,这里写的有一个错误(重新创建元素)。我使用了数组,如您所见,现在这无关紧要。

<?php
$arr1 = array();
$arr2 = array();
for ($i = 0; $i < 10000000; $i++) {
    $arr1[$i] = 'a';
    $arr2[$i] = 'a';
}

$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    $arr1[$i] = null;
}
$elapsed = microtime(true) - $start;

echo 'took '. $elapsed .'seconds<br>';

$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    unset($arr2[$i]);
}
$elapsed = microtime(true) - $start;

echo 'took '. $elapsed .'seconds<br>';

But i can only test it on an PHP 5.5.9 server, here the results: - took 4.4571571350098 seconds - took 4.4425978660583 seconds

但我只能在 PHP 5.5.9 服务器上对其进行测试,结果如下: - 耗时 4.4571571350098 秒 - 耗时 4.4425978660583 秒

I prefer unsetfor readability reasons.

我更喜欢unset可读性的原因。

回答by zero8

unsetcode if not freeing immediate memory is still very helpful and would be a good practice to do this each time we pass on code steps before we exit a method. take note its not about freeing immediate memory. immediate memory is for CPU, what about secondary memory which is RAM.

unset如果不释放即时内存,代码仍然非常有用,并且在每次我们在退出方法之前传递代码步骤时都这样做是一个很好的做法。请注意,这与释放即时内存无关。即时内存是用于 CPU 的,那是 RAM 的二级内存呢。

and this also tackles about preventing memory leaks.

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

please see this link http://www.hackingwithphp.com/18/1/11/be-wary-of-garbage-collection-part-2

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

i have been using unset for a long time now.

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

better practice like this in code to instanly unset all variable that have been used already as array.

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

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

and just unset($data);to free all variable usage.

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

please see related topic to unset

请参阅相关主题以取消设置

How important is it to unset variables in PHP?

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

[bug]

[漏洞]