Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is passing by reference slower in this code?

Tags:

php

I've encountered something that seems like a strange performance problem. Running this code:

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

?>

I get these results:

sum 548521
time taken 12.37544798851
sum 551236
time taken 0.29530310630798

What's going on here? It seems to be connected to the fact that I insert sub-arrays into the array, though I don't see why passing by reference should be that much slower.

(this is on PHP Version 5.3.3-7+squeeze14 with Suhosin Patch 0.9.9.1)

(edit: fixed using of unset variables, still the same result)

like image 256
ymgve Avatar asked Dec 10 '12 11:12

ymgve


2 Answers

You're accessing values from another scope - that's always slower than only using ones that are defined within the function itself. Here's a nice blog post explaining it, even though that's not its primary topic: PHP internals: When does foreach copy?

like image 51
Narf Avatar answered Oct 13 '22 01:10

Narf


It is just my guess but I think we could explain it like this:

  • when using no reference a local variable is created (that is directly pointing to a memory) and the loop goes like:
    • $i = 0; $foo = 499; $test[499] = array(); $test[499][] = 2; "commit" directly to a memory
    • finaly, the value $test is then returned - reading directly from the memory pointer
  • when using referenced value, the variable passed is like a pointer to a pointer (that is finally pointing to a memory)
    • in this case the loop looks like:
    • $i = 0; $foo = 354; $test[354] = array(); $test[354][] = 7; "commit" to a memory via pointer to a memory pointer

I guess therefore there is at least one more step neccessary when working with referenced variables...

like image 24
shadyyx Avatar answered Oct 13 '22 02:10

shadyyx