2012-12-10 12 views
7

Napotkałem coś, co wydaje się dziwnym problemem wydajności. Uruchomienie tego kodu:Dlaczego przekazywanie przez odniesienie jest wolniejsze w tym kodzie?

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

?> 

mogę uzyskać te wyniki:

sum 548521 
time taken 12.37544798851 
sum 551236 
time taken 0.29530310630798 

Co tu się dzieje? Wydaje się, że jest to związane z tym, że wstawiam pod-tablice do tablicy, chociaż nie rozumiem, dlaczego przekazywanie przez odniesienie powinno być o wiele wolniejsze.

(jest to na PHP Version 5.3.3-7 + squeeze14 z Suhosin patch 0.9.9.1)

(edit: stałe za pomocą zmiennych wyłączony, wciąż ten sam wynik)

+6

Gdzie '$ array' przyjść od? –

+1

Powracanie według wartości nie jest bezpłatne. –

+0

Nie znam odpowiedzi (ale byłbym zainteresowany poznaniem jej), ale chciałbym zauważyć, że odniesienia w PHP nie są wskaźnikami. Są w rzeczywistości poziomem pośrednictwa. Korzystając z referencji, tłumacz najpierw musi przejrzeć referencję, a następnie sprawdzić podaną wartość. Bez referencji jest o krok mniejszy. To może być przyczyną spowolnienia, które tu widzisz. – troelskn

Odpowiedz

1

To tylko moje przypuszczenie, ale myślę, że moglibyśmy to wyjaśnić tak:

  • przy użyciu żadnego odniesienia zmienna lokalna jest utworzony (to znaczy bezpośrednio wskazuje na pamięć) i pętla wygląda następująco:
    • $ i = 0; $ foo = 499; $ test [499] = array(); $ test [499] [] = 2; „Popełnić” bezpośrednio do pamięci
    • finaly, zmienna $ Test wartość jest następnie powrócił - odczyt bezpośrednio od wskaźnika pamięci
  • przy użyciu wartości odwołuje zmienna przekazywana jest jak wskaźnik do wskaźnika (czyli wreszcie wskazując na pamięć)
    • w tym przypadku pętla wygląda następująco:
    • $ i = 0; $ foo = 354; $ test [354] = array(); $ test [354] [] = 7; „Popełnić” do pamięci poprzez wskaźnik do wskaźnika pamięci

Chyba dlatego istnieje co najmniej jeden krok neccessary podczas pracy z odnośnych zmiennych ...

Powiązane problemy