2012-12-10 8 views
7

Ich habe etwas gefunden, das wie ein seltsames Leistungsproblem scheint. Das Ausführen dieses Code:Warum wird in diesem Code langsamer als Referenz weitergegeben?

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

?> 

ich diese Ergebnisse erhalten:

sum 548521 
time taken 12.37544798851 
sum 551236 
time taken 0.29530310630798 

Was ist hier los? Es scheint mit der Tatsache verbunden zu sein, dass ich Sub-Arrays in das Array einfüge, obwohl ich nicht verstehe, warum die Weitergabe durch Referenz so viel langsamer sein sollte.

(dies ist auf der PHP-Version 5.3.3-7 + squeeze14 mit Suhosin-Patch 0.9.9.1)

(edit: Fest Verwendung von nicht definierter Variablen, noch das gleiche Ergebnis)

+6

Wo '$ array' kommen von? –

+1

Rückgabe nach Wert ist nicht kostenlos. –

+0

Ich kenne die Antwort nicht (aber ich würde es gerne wissen), aber ich würde bemerken, dass Referenzen in PHP keine Zeiger sind. Sie sind in der Tat eine Ebene der Indirektion. Wenn Sie also eine Referenz verwenden, muss der Interpreter zuerst die Referenz nachschlagen und dann den Referenzwert nachschlagen. Ohne Referenzen ist es ein Schritt weniger. Dies könnte die Ursache für die Verlangsamung sein, die Sie hier sehen. – troelskn

Antwort

1

Sie zugreifen Werte aus einem anderen Bereich - das ist immer langsamer als nur diejenigen, die innerhalb der Funktion selbst definiert sind. Hier ist eine schöne Blog-Post es zu erklären, auch wenn das nicht sein primäres Thema: PHP internals: When does foreach copy?

1

Es ist nur meine Vermutung, aber ich denke, dass wir es so erklären konnten:

  • wenn eine lokale Variable keine Referenz verwendet ist erstellt (das direkt auf einen Speicher zeigt) und die Schleife geht wie folgt:
    • $ i = 0; $ foo = 499; $ test [499] = array(); $ test [499] [] = 2; „Commit“ direkt auf eine Speicher
    • finaly, wird der Wert $ Test dann zurückgegeben -
  • bei der Verwendung von referenzierten Wert direkt aus dem Speicherzeiger zu lesen, übergeben die Variable ist wie ein Zeiger auf einen Zeiger (dh schließlich zeigt auf einen Speicher)
    • in diesem Fall sieht die Schleife wie folgt aus:
    • $ i = 0; $ foo = 354; $ test [354] = array(); $ test [354] [] = 7; „Verpflichten“ zu einem Speicher über Zeiger auf einen Speicherzeiger

Ich denke, deshalb gibt es zumindest ein weiterer Schritt notwendig, wenn mit referenzierten Variablen arbeiten ...

Verwandte Themen