Especially, if you are a start-up, all it takes is a fine combination of:
- a bad coder (with an arrogant attitude of “code first + optimize later”)
- and 1000 simultaneous requests
to bring each of your servers to its “knees”.
On part 1, I’ve mentioned the cost of a million items when we are using arrays in PHP.
In this part, I want to highlight related features when we are passing such arrays to functions.
- version 1: array of arrays: passed by value
- version 2: array of arrays: passed by reference
- version 3a: array of objects: passed by value and reassigned objects in function
- version 3b: array of objects: passed by value without reassigned objects
- version 4: array of objects: passed by reference
Let’s see the first version of the code:
$row) {
$row['a'] = strrev($row['a']);
$array[$i] = $row;
}
return $array;
}
$arr = [];
$L = 1000000;
$S = 'abcdefghijklmnopqrstuvwxyz';
mt_srand();
for($i = 1; $i <= $L; $i++) {
$row = [
'a' => str_shuffle($S),//string
'b' => mt_rand(0, $L) / mt_rand(1, $L),//float
'c' => mt_rand(-1000, 1000),//int
];
$arr[] = $row;
}
echo '1 item 0 -> a:' . ($arr[0]['a']) . PHP_EOL;
$arr2 = myProcess($arr);
echo '1 item 0 -> a:' . ($arr[0]['a']) . PHP_EOL;
echo '2 item 0 -> a:' . ($arr2[0]['a']) . PHP_EOL;
$t1 = microtime(true);
$mem = memory_get_usage(true);
echo 'Array of ' . number_format($L) . ' arrays.' . PHP_EOL;
echo 'Time taken: ' . number_format($t1 - $t0, 3) . 'ms.' . PHP_EOL;
echo 'Memory usage: ' . number_format($mem / 1024, 1) . 'KB.' . PHP_EOL;
?>
I’ve got the best results when I used the version 4:
$row) {
$row->a = strrev($row->a);
//$array[$i] = $row; //no need because objects in arrays have references
}
//return $array; //no need to return, because we are modifying the array given by reference
}
class myClass
{
public $a;
public $b;
public $c;
function __construct($a, $b, $c)
{
$this->a = $a;
$this->b = $b;
$this->c = $c;
}
}
$arr = [];
$L = 1000000;
$S = 'abcdefghijklmnopqrstuvwxyz';
mt_srand();
for($i = 1; $i <= $L; $i++) {
$row = new myClass(
str_shuffle($S),//string
mt_rand(0, $L) / mt_rand(1, $L),//float
mt_rand(-1000, 1000)
);
$arr[] = $row;
}
echo '1 object 0 -> a:' . ($arr[0]->a) . PHP_EOL;
myProcess($arr);
echo '1 object 0 -> a:' . ($arr[0]->a) . PHP_EOL;
$t1 = microtime(true);
$mem = memory_get_usage(true);
echo 'Array of ' . number_format($L) . ' custom objects.' . PHP_EOL;
echo 'Time taken: ' . number_format($t1 - $t0, 3) . 'ms.' . PHP_EOL;
echo 'Memory usage: ' . number_format($mem / 1024, 1) . 'KB.' . PHP_EOL;
?>
You can see all the files on my github project.
The surprising cases for me were version 3a and version 3b. Simply, I didn’t expect a difference of 50MB because I thought they are effectively doing the same job.
And here is the chart to compare them:
Note: This time, I didn’t use the logarithmic scale.