Using PHP8.3.0, testing SplFixedArray, I have this sample code
<?php
declare(strict_types=1);
$res = [];
$t = microtime(true);
for ($i = 1; $i <= 1_000_000; ++$i) {
if (1) {
$new = new SplFixedArray(3);
$new[0] = "foo";
$new[1] = "bar";
$new[2] = "baz";
$res[] = $new;
} else {
$res[] = [
0 => "foo",
1 => "bar",
2 => "baz",
];
}
}
$t = microtime(true) - $t;
var_dump(
[
'memory_get_peak_usage(true) / 1024 / 1024' => memory_get_peak_usage(true) / 1024 / 1024,
'memory_get_peak_usage() / 1024 / 1024' => memory_get_peak_usage() / 1024 / 1024,
't' => $t,
]
);
and when I benchmark it with hyperfine, first using arrays and then using SplFixedArray:
$ hyperfine --warmup 10 'php spl.php'
Benchmark 1: php spl.php
Time (mean ± σ): 52.7 ms ± 0.8 ms [User: 43.6 ms, System: 6.0 ms]
Range (min … max): 51.4 ms … 56.2 ms 57 runs
$ hyperfine --warmup 10 'php spl.php'
Benchmark 1: php spl.php
Time (mean ± σ): 321.1 ms ± 6.1 ms [User: 267.6 ms, System: 34.8 ms]
Range (min … max): 315.6 ms … 335.9 ms 10 runs
the array method average 52ms, SplFixedArray averaged 321ms
And when I look at memory consumption,
$ time php spl.php
/home/hans/projects/headless-chomium-recorder/tests/hans/spl.php:23:
array(3) {
'memory_get_peak_usage(true) / 1024 / 1024' =>
double(26.0078125)
'memory_get_peak_usage() / 1024 / 1024' =>
double(16.383125305176)
't' =>
double(0.047396898269653)
}
real 0m0.060s
user 0m0.038s
sys 0m0.018s
$ time php spl.php
/home/hans/projects/headless-chomium-recorder/tests/hans/spl.php:23:
array(3) {
'memory_get_peak_usage(true) / 1024 / 1024' =>
double(214.00390625)
'memory_get_peak_usage() / 1024 / 1024' =>
double(210.30303955078)
't' =>
double(0.28029799461365)
}
real 0m0.321s
user 0m0.301s
sys 0m0.000s
array use 26MB RAM, SplFixedArray use 214MB RAM..
Seems that array is much better than SplFixedArray with both in memory consumption and speed,
Quoting the SplFixedArray documentation:
The advantage is that it uses less memory than a standard array.
But I see the exact opposite effect, for me SplFixedArray seems to be using ~8 times more memory, why?
The reason you're seeing this is because you're not actually creating new subarrays in the array example; while you are creating new arrays in the SplFixedArray example.
When you write
[
0 => "foo",
1 => "bar",
2 => "baz",
];
then this subarray is interned, i.e. only created only once, and then shared between all those array elements. This also explains why the memory usage is so low. If you start modifying any of these arrays, they "separate" out and create actual array instances. You'll also see the memory usage rise if you start modifying those arrays.
For SplFixedArray, you're creating a new array in each iteration.
TL;DR: incorrect comparison.