peter.karakas
peter.karakas

Reputation: 151

How does PHP use the parameters passed by ref or value?

I did a little experiment and I got a surprising result (for me at least). I have written 6 functions to sum up an array in PHP in different ways. Here you can see the results:

PHP ver: 5.5.36
foreach_by_value():     1.1668000221252
foreach_by_ref():       0.38018989562988
array_sum_by_value():   0.11428999900818
array_sum_by_ref():     0.91070008277893
for_by_value():         0.50360298156738
for_by_ref():           1.2752962112427

As you can see, passing the array by reference sometimes makes it faster on the other cases slower. A don't really know what is the reason behind this.

Here is the code that I used for testing:

echo phpversion() . "\n";

const N = 100000;
const REPEAT = 100;

for ($i = 0;$i < N;$i++) {
    $array[] = rand(0, 10000);
}

function foreach_by_value($a) {
    $sum = 0;
    foreach($a as $number) {
        $sum += $number;
    }
}

function foreach_by_ref(&$a) {
    $sum = 0;
    foreach($a as $number) {
        $sum += $number;
    }
}

function array_sum_by_value($a) {
    $sum = array_sum($a);
}

function array_sum_by_ref(&$a) {
    $sum = array_sum($a);
}

function for_by_value($array) {
    $sum = 0;
    $count = count($array);
    for($i = 0;$i < $count;$i++) {
        $sum += $array[$i];
    }
}

function for_by_ref(&$array) {
    $sum = 0;
    $count = count($array);
    for($i = 0;$i < $count;$i++) {
        $sum += $array[$i];
    }
}


$start_time = microtime(true);
for ($i = 0;$i < REPEAT;$i++) {
    foreach_by_value($array);
}
$finish_time = microtime(true);
echo "foreach_by_value(): \t" . ($finish_time - $start_time) . "\n";

$start_time = microtime(true);
for ($i = 0;$i < REPEAT;$i++) {
    foreach_by_ref($array);
}
$finish_time = microtime(true);
echo "foreach_by_ref(): \t" . ($finish_time - $start_time) . "\n";


$start_time = microtime(true);
for ($i = 0;$i < REPEAT;$i++) {
    array_sum_by_value($array);
}
$finish_time = microtime(true);
echo "array_sum_by_value(): \t" . ($finish_time - $start_time) . "\n";

$start_time = microtime(true);
for ($i = 0;$i < REPEAT;$i++) {
    array_sum_by_ref($array);
}
$finish_time = microtime(true);
echo "array_sum_by_ref(): \t" . ($finish_time - $start_time) . "\n";

$start_time = microtime(true);
for ($i = 0;$i < REPEAT;$i++) {
    for_by_value($array);
}
$finish_time = microtime(true);
echo "for_by_value(): \t" . ($finish_time - $start_time) . "\n";

$start_time = microtime(true);
for ($i = 0;$i < REPEAT;$i++) {
    for_by_ref($array);
}
$finish_time = microtime(true);
echo "for_by_ref(): \t\t" . ($finish_time - $start_time) . "\n";

Upvotes: 0

Views: 65

Answers (1)

IVO GELOV
IVO GELOV

Reputation: 14269

  • foreach_by_value - cycle enumerates the array and copies the current value into temp variable $number, so this takes additional time;
  • foreach_by_ref - cycle enumerates the array and does not copy anything, just add to the sum;
  • array_sum_by_value - internal function (written in C++) enumerates the array and calculates the sum, so this is the fastest result;
  • array_sum_by_ref - internal function (written in C++) enumerates the array, but since each internal invocation to next() is by reference, this requires additional time for redirection (for each element of the array);
  • for_by_value - it does not use any temp variable, but since it uses indexing instead of current() and next(), this takes more time than foreach_by_ref;
  • for_by_ref - since the argument to function is passed by reference, for each access to the argument there is one redirection, and it takes time;

Upvotes: 2

Related Questions