在 PHP (>= 5.0) 中,通过引用传递更快吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/178328/
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
In PHP (>= 5.0), is passing by reference faster?
提问by Hanno Fietz
In PHP, function parameters can be passed by reference by prepending an ampersand to the parameter in the function declaration, like so:
在 PHP 中,函数参数可以通过在函数声明中的参数前面加上一个和号来通过引用传递,如下所示:
function foo(&$bar)
{
// ...
}
Now, I am aware that this is notdesigned to improve performance, but to allow functions to change variables that are normally out of their scope.
现在,我意识到这不是为了提高性能,而是为了允许函数更改通常超出其范围的变量。
Instead, PHP seems to use Copy On Write to avoid copying objects (and maybe also arrays) until they are changed. So, for functions that do not change their parameters, the effect should be the same as if you had passed them by reference.
相反,PHP 似乎使用 Copy On Write 来避免复制对象(也可能是数组),直到它们被更改。所以,对于不改变参数的函数,效果应该和你通过引用传递一样。
However, I was wondering if the Copy On Write logic maybe is shortcircuited on pass-by-reference and whether that has any performance impact.
但是,我想知道 Copy On Write 逻辑是否可能在传递引用时短路,以及这是否对性能有任何影响。
ETA: To be sure, I assume that it's not faster, and I am well aware that this is not what references are for. So I think my own guesses are quite good, I'm just looking for an answer from someone who really knows what's definitely happening under the hood. In five years of PHP development, I've always found it hard to get quality information on PHP internals short from reading the source.
ETA:可以肯定的是,我认为它不会更快,而且我很清楚这不是引用的用途。所以我认为我自己的猜测非常好,我只是在寻找真正知道幕后肯定发生了什么的人的答案。在五年的 PHP 开发中,我总是发现很难通过阅读源代码来获得有关 PHP 内部结构的高质量信息。
采纳答案by Paul Dixon
The Zend Engine uses copy-on-write, and when you use a reference yourself, it incurs a little extra overhead. Can only find this mentionat time of writing though, and comments in the manualcontain other links.
Zend 引擎使用写时复制,当您自己使用引用时,会产生一些额外的开销。但是只能在撰写本文时找到此提及,并且手册中的评论包含其他链接。
(EDIT) The manual page on Objects and referencescontains a little more info on how object variables differ from references.
(编辑)对象和引用的手册页包含更多关于对象变量与引用不同的信息。
回答by ikary
In a test with 100 000 iterations of calling a function with a string of 20 kB, the results are:
在使用 20 kB 的字符串调用函数进行 100 000 次迭代的测试中,结果为:
Function that just reads / uses the parameter
仅读取/使用参数的函数
pass by value: 0.12065005 seconds
pass by reference: 1.52171397 seconds
Function to write / change the parameter
写入/更改参数的功能
pass by value: 1.52223396 seconds
pass by reference: 1.52388787 seconds
Conclusions
结论
Pass the parameter by value is always faster
If the function change the value of the variable passed, for practical purposes is the same as pass by reference than by value
按值传递参数总是更快
如果函数改变了传递的变量的值,对于实际目的来说与通过引用传递而不是通过值传递是一样的
回答by Petah
I ran some test on this because I was unsure of the answers given.
我对此进行了一些测试,因为我不确定给出的答案。
My results show that passing large arrays or strings by reference IS significantly faster.
我的结果表明,通过引用传递大数组或字符串的速度要快得多。
Here are my results:

这是我的结果:

The Y axis (Runs) is how many times a function could be called in 1 second * 10
Y 轴 (Runs) 是在 1 秒内可以调用函数的次数 * 10
The test was repeated 8 times for each function/variable
对每个函数/变量重复测试 8 次
And here is the variables I used:
这是我使用的变量:
$large_array = array_fill(PHP_INT_MAX / 2, 1000, 'a');
$small_array = array('this', 'is', 'a', 'small', 'array');
$large_object = (object)$large_array;
$large_string = str_repeat('a', 100000);
$small_string = 'this is a small string';
$value = PHP_INT_MAX / 2;
These are the functions:
这些是函数:
function pass_by_ref(&$var) {
}
function pass_by_val($var) {
}
回答by Vladimir Fesko
I have experimented with values and references of 10k bytes string passing it to two identical function. One takes argument by value and the second one by reference. They were common functions - take argument, do simple processing and return a value. I did 100 000 calls of both and figured out that references are not designed to increase performance - profit of reference was near 4-5% and it grows only when string becomes large enough (100k and longer, that gave 6-7% improvement). So, my conclusion is do not use references to increase perfomance, this stuff is not for that.
我已经尝试过将 10k 字节字符串的值和引用传递给两个相同的函数。一个按值接受参数,第二个按引用接受。它们是常见的函数——接受参数,做简单的处理并返回一个值。我做了 100 000 次调用,发现引用并不是为了提高性能——引用的利润接近 4-5%,只有当字符串变得足够大时才会增长(100k 和更长,这提供了 6-7% 的改进) . 所以,我的结论是不要使用引用来提高性能,这个东西不是为了那个。
I used PHP Version 5.3.1
我使用的是 PHP 版本 5.3.1
回答by Greg
I'm pretty sure that no, it's not faster. Additionally, it says specifically in the manual not to try using references to increase performance.
我很确定不,它不会更快。此外,它在手册中特别指出不要尝试使用引用来提高性能。
Edit: Can't find where it says that, but it's there!
编辑:找不到它说的地方,但它在那里!
回答by Melsi
There is nothing better than a testing piece of code
没有什么比一段测试代码更好的了
<?PHP
$r = array();
for($i=0; $i<500;$i++){
$r[]=5;
}
function a($r){
$r[0]=1;
}
function b(&$r){
$r[0]=1;
}
$start = microtime(true);
for($i=0;$i<9999;$i++){
//a($r);
b($r);
}
$end = microtime(true);
echo $end-$start;
?>
Final result! The bigger the array (or the greater the count of calls) the bigger the difference. So in this case, calling by reference is faster because the value is changed inside the function.
最后结果!数组越大(或调用次数越多),差异就越大。所以在这种情况下,通过引用调用更快,因为值在函数内部发生了变化。
Otherwise there is no real difference between "by reference" and "by value", the compiler is smart enough not to create a new copy each time if there is no need.
否则“按引用”和“按值”之间没有真正的区别,编译器足够聪明,如果不需要,不会每次都创建一个新副本。
回答by Bob Ray
I tried to benchmark this with a real-world example based on a project I was working on. As always, the differences are trivial, but the results were somewhat unexpected. For most of the benchmarks I've seen, the called function doesn't actually change the value passed in. I performed a simple str_replace() on it.
我试图用一个基于我正在处理的项目的真实示例来对此进行基准测试。与往常一样,差异是微不足道的,但结果有些出乎意料。对于我见过的大多数基准测试,被调用的函数实际上并没有改变传入的值。我对它执行了一个简单的 str_replace() 。
**Pass by Value Test Code:**
$originalString=''; // 1000 pseudo-random digits
function replace($string) {
return str_replace('1', 'x',$string);
}
$output = '';
/* set start time */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tstart = $mtime;
set_time_limit(0);
for ($i = 0; $i < 10; $i++ ) {
for ($j = 0; $j < 1000000; $j++) {
$string = $originalString;
$string = replace($string);
}
}
/* report how long it took */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tend = $mtime;
$totalTime = ($tend - $tstart);
$totalTime = sprintf("%2.4f s", $totalTime);
$output .= "\n" . 'Total Time' .
': ' . $totalTime;
$output .= "\n" . $string;
echo $output;
Pass by Reference Test Code
通过参考测试代码
The same except for
除了相同
function replace(&$string) {
$string = str_replace('1', 'x',$string);
}
/* ... */
replace($string);
Results in seconds (10 million iterations):
结果以秒为单位(1000 万次迭代):
PHP 5
Value: 14.1007
Reference: 11.5564
PHP 7
Value: 3.0799
Reference: 2.9489
The difference is a fraction of a millisecond per function call, but for this use case, passing by reference is faster in both PHP 5 and PHP 7.
差异是每次函数调用的几分之一毫秒,但对于这个用例,在 PHP 5 和 PHP 7 中通过引用传递更快。
(Note: the PHP 7 tests were performed on a faster machine -- PHP 7 is faster, but probably not that much faster.)
(注意:PHP 7 测试是在更快的机器上执行的——PHP 7 更快,但可能没有那么快。)
回答by orfruit
Is simple, there is no need to test anything. Depends on use-case.
很简单,不需要测试任何东西。取决于用例。
Pass by value will ALWAYS BE FASTER BY VALUE than reference for small amount of arguments. This depends by how many variables that architecture allows to be passed through registers (ABI).
对于少量参数,按值传递总是比按值传递快。这取决于架构允许通过寄存器 (ABI) 传递的变量数量。
For example x64 will allow you 4 values 64 bit each to be passed through registers. https://en.wikipedia.org/wiki/X86_calling_conventions
例如,x64 将允许您通过寄存器传递 4 个 64 位值。 https://en.wikipedia.org/wiki/X86_calling_conventions
This is because you don't have to de-referentiate the pointers, just use value directly.
这是因为您不必取消引用指针,只需直接使用 value。
If your data that needs to be passed is bigger than ABI, rest of values will go to stack. In this case, a array or a object (which in instance is a class, or a structure + headers) will ALWAYS BE FASTER BY REFERENCE.
如果您需要传递的数据大于 ABI,则其余值将进入堆栈。在这种情况下,一个数组或一个对象(在实例中是一个类,或一个结构 + 头文件)总是通过引用更快。
This is because a reference is just a pointer to your data (not data itself), fixed size, say 32 or 64 bit depending on machine. That pointer will fit in one CPU register.
这是因为引用只是指向您的数据(而不是数据本身)的指针,固定大小,例如 32 位或 64 位,具体取决于机器。该指针将适合一个 CPU 寄存器。
PHP is written in C/C++ so I'd expect to behave the same.
PHP 是用 C/C++ 编写的,所以我希望表现得一样。
回答by Micha? Rudnicki
There is no need for adding & operator when passing objects. In PHP 5+ objects are passed by reference anyway.
传递对象时无需添加 & 运算符。在 PHP 5+ 中,对象无论如何都是通过引用传递的。

