【问题标题】:PHP performance issue: pass referenced variable as non-ref parameterPHP 性能问题:将引用变量作为非引用参数传递
【发布时间】:2018-05-01 23:59:36
【问题描述】:
function M1($x, $y){}
function M2(&$x, $y){}
function M3(&$x, &$y){}

$arr = ['a' => ['b' => range(1, 1000)]];
$ref_arr = &$arr['a'];

$var = $ref_arr['b'];
$ref = &$ref_arr['b'];

//N->N, N->N
//0.003000020980835 sec.
for($i = 0; $i < 10000; ++$i)
    M1($var, $var);

//N->R, N->N   (slow)
//0.59903407096863 sec.
for($i = 0; $i < 10000; ++$i)
    M2($var, $var);

//N->R, N->R
//0.003000020980835 sec.
for($i = 0; $i < 10000; ++$i)
    M3($var, $var);

//R->N, R->N   (very slow)
//1.1980690956116 sec.
for($i = 0; $i < 10000; ++$i)
    M1($ref, $ref);

//R->R, R->N   (slow)
//0.58603405952454 sec.
for($i = 0; $i < 10000; ++$i)
    M2($ref, $ref);

//R->R, R->R
//0.003000020980835 sec.
for($i = 0; $i < 10000; ++$i)
    M3($ref, $ref);

据我所知,当将引用变量作为非引用参数传递时,PHP 会复制该值。所以这条线耗时最长。

M1($ref, $ref); //1.1980690956116 秒。

但是如何解释这两条线的表现呢?

M2($var, $var); //0.59903407096863 秒。

M3($var, $var); //0.003000020980835 秒。

【问题讨论】:

  • PHP 使用写时复制。所以传递参数不需要复制。永远不需要使用引用来提高性能。仅当函数需要修改调用者的变量时才使用它们。
  • 对于 "M2($var, $var)" 我认为 $var pass by ref 被复制了。所以 "M3($var, $var)" 应该复制 $var 两次,但实际上并没有发生。
  • 可以看到这3个函数没有修改任何值。因此,对于您的结论,它们应该花费相同的时间来运行,但它们是不同的。 @Barmar
  • 是的,我想我所说的对于普通变量来说是正确的。显然需要对参考变量进行特殊处理。
  • 你运行了多少次以获得每个函数的平均值?

标签: php performance pass-by-reference


【解决方案1】:

几年过去了,没有人给我答案,所以我决定自己回答。

原因仍然是PHP中的COPY-ON-WRITE机制,但是当传递不同引用类型的参数时,复制发生在函数调用开始之前。

定义:

  • N 表示非参考变量
  • R 代表参考变量
  • -> 用于参数传递

这3种形式不会触发参数复制:

  • N -> N
  • R -> R
  • N(参考计数 = 1)-> R

对于这两种形式,总是会发生参数复制。

  • R -> N
  • N(参考计数 > 1)-> R

所以当你决定调用一个带有引用参数的函数(通常是数组函数,如sortreset)时,传递一个引用计数大于 1 的数组并不是一个好主意。

不好的例子:

$arr1 = [];
$arr2 = $arr1;
sort($arr1);

好例子:

$arr1 = [];
$arr2 = $arr1;
unset($arr2);
sort($arr1);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    • 2012-11-13
    相关资源
    最近更新 更多