7

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

<?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

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

(这是在带有 Suhosin 补丁 0.9.9.1 的 PHP 版本 5.3.3-7+squeeze14 上)

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

4

2 回答 2

1

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

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

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

于 2012-12-10T11:13:12.793 回答
1

您正在从另一个范围访问值 - 这总是比仅使用在函数本身中定义的值要慢。这是一篇很好的博客文章来解释它,尽管这不是它的主要主题:PHP 内部:什么时候 foreach 复制?

于 2012-12-10T11:08:54.917 回答