引用php函数中的变量有助于节省内存吗?

时间:2010-06-27 01:04:56

标签: php

例如,当比较管理内存的方式时,以下两个函数是否相同:

$hello = 'hello';

my_echo($hello);

//Better or worse than
my_echo_ref($hello);

//case 1, no referencing:
function my_echo($word) {
 echo $word;
} 

//case 2, referencing:
function my_echo_ref(&$word) {
  echo $word;
}

4 个答案:

答案 0 :(得分:27)

我不知道这个来源有多可靠,但这是一篇非常有趣的文章(自2008年起),解释了如何处理变量:

The Truth About PHP Variables

它说

  

我想写这篇文章来澄清PHP中常见的误解 - 在传递大变量时使用引用是一种节省内存的好方法。

  

(...)虽然上面的参考解释对于一般的理解是足够的,但理解PHP如何在内部处理变量赋值通常很有用。这是我们介绍zval概念的地方。

     

zvals是一个内部PHP结构,用于存储变量。每个zval包含各种信息,我们将在这里重点介绍如下:

     
      
  • 存储在zval中的实际数据 - 在我们的示例中,这将是'hello!'或'goodbye!'
  •   
  • is_ref布尔标志
  •   
  • 一个ref_count计数器
  •   
     

(...)

  

(...)当您按值分配变量时(例如在示例1中),它不会创建新的zval,它只是将两个变量指向相同的zval并将zval的ref_count增加1。 “等等!”我听到你哭了,“这不是通过引用传递吗?”嗯,虽然听起来一样,所有 PHP正在做的是推迟任何复制,直到它真的必须 - 它知道这一点,因为is_ref仍然是假的。 (...)

和结论:

  

您可以看到,除非开发人员完全一致,否则通过引用传递变量很容易导致增加内存使用量。


除此之外,我用get_memory_usage()运行了几次你的代码并且内存消耗没有差别(但这并不一定意味着什么,当一个人实际上对变量做某事时,内存消耗可能不同)。

答案 1 :(得分:5)

记录(php 7.0 - win32)

我正在测试它(我将一个变量传递给一个函数,然后我更改了函数内部的值),我发现:

a)unset($ var)和$ var = null同等行为。

b)通过引用而不是按值传递数组,在某个时刻将内存使用量增加一倍。为什么?,我不知道。我用memory_get_peak_usage()找到了它。但是,memory_get_usage()不会改变,所以我猜它复制了信息(可能在时间变量中),然后丢弃。

例如:(记忆只是近似值)

  $var= (10mb of data as an array)  = memory peak 10mb.
  function functionval($var) {
       $var= (100mb of data) = memory peak 110mb.
  }
  function functionref(&$var) {
       $var= (100mb of data) = memory peak 210mb. !!! 
  }

  $var= (100mb of data as an array)  = memory peak 100mb.
  function functionval($var) {
       $var= (10mb of data) = memory peak 110mb.
  }
  function functionref(&$var) {
       $var= (10mb of data) = memory peak 120mb. !!! 
  }

  $var= (100mb of data as an array)  = memory peak 100mb.
  function functionval($var) {
       $var= (100mb of data) = memory peak 200mb.
  }
  function functionref(&$var) {
       $var= (100mb of data) = memory peak 300mb. !!! <-- why???
  }

  $var= (100mb of data as an array)  = memory peak 100mb.
  function functionval($var) {
       not changing the data. = memory peak 100mb.
  }
  function functionref(&$var) {
       not changing the data. = memory peak 100mb.
  }

c)将参数作为值或引用传递实际上不会改变执行时间。

d)传递对象作为参考,在某些时候将内存使用量加倍。

答案 2 :(得分:3)

如果要在函数内部修改传递的变量,则通过引用传递是不增加内存的好方法。

在我的测试(PHP 5.5.9)中,只有在不更改传递的$变量的情况下,通过引用或值递归传递才会产生任何显着差异

每当函数修改变量并通过值将其传递给另一个函数时,就会发生内存中的重复。

以下是我的测试结果。

enter image description here

如果您想尝试以下是PHP代码:

    global $m1, $recursion_level;

    $variable = []; // array with dummy data
    $data = str_pad('*', 256); // Dummy data
    $recursion_level = 5; // recursion levels of by_val and by_ref functions

    $m1 = memory_get_usage(); // measuring actual memory usage before setting/filling $variable

    for ($i = 1; $i < 1000; $i++) {
        $variable[] = $data;
    }

    print 'APROX size of $variable: ' . ( memory_get_usage() - $m1 ) . '<br/>';

    // recursive function passing $variable by reference
    function by_ref(&$ref, $level) {
        global $m1, $recursion_level;

        $ref[0] = ''; // Changing one element does the difference...

        print 'LEVEL ' . ($recursion_level - $level) . ': ' . (memory_get_usage() - $m1) . '<br/>';

        if ($level-- > 0) {
            by_ref($ref, $level);
        }
    }

    // recursive function passing $variable by value
    function by_val($val, $level) {
        global $m1, $recursion_level;

        print 'LEVEL ' . ($recursion_level - $level) . ': ' . (memory_get_usage() - $m1) . '<br/>';

        $val[0] = ''; // Changing one element does the difference...

        if ($level-- > 0) {
            by_val($val, $level);
        }
    }

    print '<br/><br/>MEMORY SIZE PASSING BY VAL<hr/>';
    by_val($variable, $recursion_level);

    print '<br/><br/>MEMORY SIZE PASSING BY REF<hr/>';
    by_ref($variable, $recursion_level);

答案 3 :(得分:0)

如果您使用数组作为数据源来构建第二个数组,并且通过为其分配变量来简化数组尺寸,那么按引用比较好。

示例:

argmax

APROX尺寸:7520
APROX尺寸:856