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 Patch 0.9.9.1 を適用した PHP バージョン 5.3.3-7+squeeze14 にあります)

(編集:未設定の変数の使用を修正しましたが、結果は同じです)

4

2 に答える 2

1

別のスコープから値にアクセスしています。これは、関数自体の中で定義されているものだけを使用するよりも常に遅くなります。これは、主要なトピックではありませんが、それを説明する素敵なブログ投稿です: PHP internals: When does foreach copy?

于 2012-12-10T11:08:54.917 に答える
1

あくまで私の推測ですが、以下のように説明できると思います。

  • 参照を使用しない場合、ローカル変数が作成され (メモリを直接指している)、ループは次のようになります。
    • $i = 0; $foo = 499; $test[499] = 配列(); $test[499][] = 2; メモリに直接「コミット」する
    • 最後に、値 $test が返されます - メモリポインタから直接読み取ります
  • 参照される値を使用する場合、渡される変数はポインターへのポインターのようなものです (最終的にはメモリを指します)。
    • この場合、ループは次のようになります。
    • $i = 0; $foo = 354; $test[354] = 配列(); $test[354][] = 7; メモリポインタへのポインタを介してメモリに「コミット」する

したがって、参照変数を操作する場合、少なくとももう 1 つの手順が必要になると思います...

于 2012-12-10T11:13:12.793 に答える