为什么在这段代码中通过引用传递较慢?

时间:2012-12-10 11:00:22

标签: php

我遇到了一些看似奇怪的性能问题。运行此代码:

<?php

function test_ref(&$test)
{
    for ($i = 0; $i < 100000; $i++)
    {
        $foo = "s" . rand(1, 1000);
        if (!array_key_exists($foo, $test))
        {
            $test[$foo] = array();
        }
        $test[$foo][] = rand(1, 10);
    }
}

function test()
{
    $test = array();
    for ($i = 0; $i < 100000; $i++)
    {
        $foo = "s" . rand(1, 1000);
        if (!array_key_exists($foo, $test))
        {
            $test[$foo] = array();
        }
        $test[$foo][] = rand(1, 10);
    }

    return $test;
}

$scriptstart = microtime(true);
$test = array();
test_ref($test);
$sum = 0;

foreach ($test as $key => $val)
{
    foreach ($val as $val2)
    {
        $sum += $val2;
    }
}

echo "sum " . $sum . "<br>";
$scriptelapsed = microtime(true) - $scriptstart;
echo "time taken " . $scriptelapsed . "<br>";

$scriptstart = microtime(true);
$test = test();
$sum = 0;

foreach ($test as $key => $val)
{
    foreach ($val as $val2)
    {
        $sum += $val2;
    }
}

echo "sum " . $sum . "<br>";
$scriptelapsed = microtime(true) - $scriptstart;
echo "time taken " . $scriptelapsed . "<br>";

?>

我得到了这些结果:

sum 548521
time taken 12.37544798851
sum 551236
time taken 0.29530310630798

这里发生了什么?这似乎与我将子数组插入数组的事实有关,但我不明白为什么通过引用传递应该慢得多。

(这是在PHP Version 5.3.3-7 + squeeze14 with Suhosin Patch 0.9.9.1)

(编辑:使用未设置的变量固定,结果仍然相同)

2 个答案:

答案 0 :(得分:1)

您正在访问来自另一个范围的值 - 这总是比仅使用在函数本身中定义的值更慢。这是一篇很好的博客文章解释它,即使这不是它的主要主题:PHP internals: When does foreach copy?

答案 1 :(得分:1)

这只是我的猜测,但我认为我们可以这样解释:

  • 当不使用引用时,创建局部变量(直接指向内存),循环如下:
    • $ i = 0; $ foo = 499; $ test [499] = array(); $ test [499] [] = 2; “直接”提交到内存
    • 最后,返回值$ test - 直接从内存指针读取
  • 使用引用值时,传递的变量就像指向指针的指针(最终指向内存)
    • 在这种情况下,循环看起来像:
    • $ i = 0; $ foo = 354; $ test [354] = array(); $ test [354] [] = 7;通过指向内存指针的指针“提交”到内存

因此我认为在使用引用变量时至少还需要一个步骤...