为了测试引用传递和值传递的性能,我使用了这个脚本。结论如下。
#!/usr/bin/php
<?php
function sum($array,$max){ // 对于引用,请使用:“&$array”
$sum=0;
for ($i=0; $i<2; $i++){
#$array[$i]++; // 取消注释此行以修改函数内的数组。
$sum += $array[$i];
}
return ($sum);
}
$max = 1E7 // 1000 万个数据点。
$data = range(0,$max,1);
$start = microtime(true);
for ($x = 0 ; $x < 100; $x++){
$sum = sum($data, $max);
}
$end = microtime(true);
echo "Time: ".($end - $start)." s\n";
/* 运行时间:
# 传递方式 修改? 时间
- ------- --------- ----
1 值 否 56 us
2 引用 否 58 us
3 值 是 129 s
4 引用 是 66 us
结论:
1. PHP 已经很聪明地处理了零拷贝/写时复制。除非需要,否则函数调用不会复制数据;只有在写入时才会复制数据。这就是为什么 #1 和 #2 的时间相似,而 #3 比 #4 慢 200 万倍。
[你永远不需要使用 &$array 来要求编译器进行零拷贝优化;它可以自己解决这个问题。]
2. 你确实使用 &$array 来告诉编译器“函数可以在原地覆盖我的参数,我不再需要原始数据了”。当我们需要复制大量内存时,这会对性能产生巨大影响。
(这是在 C 中唯一的方法,数组总是作为指针传递)
3. & 的另一个用途是指定应在何处*返回*数据。(例如,exec() 使用的方式)。
(这是一种类似 C 的传递输出指针的方法,而 PHP 函数通常返回复杂类型或数组中的多个答案)
4. 只有函数定义包含 & 这一点是不方便的。调用者也应该包含它,至少作为语法糖。否则
会导致代码难以阅读:因为阅读函数调用的人不会期望它通过引用传递。目前,
必须使用注释编写按引用传递的函数调用,如下所示:
$sum = sum($data,$max); //警告,$data 通过引用传递,并且可能会被修改。
5. 有时,引用传递可以由调用者选择,而不是函数定义。PHP 不允许这样做,但对于调用者来说,决定将数据作为引用传递是有意义的。即“我已经完成了这个变量,可以覆盖它在内存中的数据了”。
*/
?>