例如,当比较管理内存的方式时,以下两个函数是否相同:
$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;
}
答案 0 :(得分:27)
我不知道这个来源有多可靠,但这是一篇非常有趣的文章(自2008年起),解释了如何处理变量:
它说
我想写这篇文章来澄清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)中,只有在不更改传递的$变量的情况下,通过引用或值递归传递才会产生任何显着差异。
每当函数修改变量并通过值将其传递给另一个函数时,就会发生内存中的重复。
以下是我的测试结果。
如果您想尝试以下是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