What's better at freeing memory with PHP: unse

2018-12-31 13:05发布

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 = null instead.

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

标签: php
12条回答
春风洒进眼中
2楼-- · 2018-12-31 13:27

I created a new performance test for unset and =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.

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

I prefer unset for readability reasons.

查看更多
大哥的爱人
3楼-- · 2018-12-31 13:27

PHP 7 is already worked on such memory management issues and its reduced up-to minimal usage.

<?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 Outpu:

took 0.16778993606567 seconds took 0.16630101203918 seconds

查看更多
高级女魔头
4楼-- · 2018-12-31 13:28

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.

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

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.

查看更多
高级女魔头
5楼-- · 2018-12-31 13:30

unset code 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.

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

i have been using unset for a long time now.

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.

please see related topic to unset

How important is it to unset variables in PHP?

[bug]

查看更多
看风景的人
6楼-- · 2018-12-31 13:35

For the record, and excluding the time that it takes:

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

It returns

First:
438296
438352
Unset:
438296
438352
Null:
438296
438352
function:
438296
438352
Reasign:
438296
520216 <-- double usage.

Conclusion, both null and unset free memory as expected (not only at the end of the execution). Also, reassigning a variable holds the value twice at some point (520216 versus 438352)

查看更多
不流泪的眼
7楼-- · 2018-12-31 13:39
<?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.

PHP 5.4 results:

  • took 0.88389301300049 seconds
  • took 2.1757180690765 seconds

PHP 5.3 results:

  • took 1.7235369682312 seconds
  • took 2.9490959644318 seconds

PHP 5.2 results:

  • took 3.0069220066071 seconds
  • took 4.7002630233765 seconds

PHP 5.1 results:

  • took 2.6272349357605 seconds
  • took 5.0403649806976 seconds

Things start to look different with PHP 5.0 and 4.4.

5.0:

  • took 10.038941144943 seconds
  • took 7.0874409675598 seconds

4.4:

  • took 7.5352551937103 seconds
  • took 6.6245851516724 seconds

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.

查看更多
登录 后发表回答