Skip to content

@Thinkscape /isAssocArrayBench.php
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
A benchmark of several methods for checking if PHP array is associative
<?php
if(!isset($argv[1])){
echo "Usage: ".$argv[0]." (number of iterations)\n";
exit(1);
}
/**
* Arrays to check
*/
$tests = array(
array(array(
'foo' => 'bar',
)),
array(array(
'bar',
'foo' => 'bar',
'baz',
)),
array(null),
array(true),
array(false),
array(0),
array(1),
array(0.0),
array(1.0),
array('string'),
array(array(0, 1, 2)),
array(new stdClass),
array_fill(0,1000,uniqid()), // big numeric array
array_fill_keys(range(2,1000,3),uniqid()), // big misaligned numeric array (=associative)
array_fill_keys( // big associative array
str_split(
str_repeat(uniqid('',true),100),
3
),
true
)
);
$iterations = (int)$argv[1];
/**
* Common methods to check associative array
*/
$methods = array(
'method1 (array_values check)' =>
function($array){
return (array_values($array) !== $array);
},
'method2 (array_keys comparison)' =>
function($array){
$array = array_keys($array); return ($array !== array_keys($array));
},
'method3 (array_filter of keys)' =>
function($array){
return count(array_filter(array_keys($array), 'is_string')) > 0;
}
);
/**
* Perform benchmark on each method
*/
foreach($methods as $name=>$func){
echo "Testing $name - $iterations iterations\n";
$time = microtime(true);
for($x=0;$x<$iterations;$x++){
foreach($tests as $array){
$func($array);
}
}
/**
* Show results
*/
$totalTime = (microtime(true) - $time);
$avgTime = $totalTime / ($iterations * count($tests));
echo " Total time: ".number_format($totalTime,5,'.',' ')." s\n";
echo " Average : ".number_format($avgTime*1000,5,'.',' ')." ms / test \n";
echo "\n";
}
@Thinkscape
Owner

PHP 5.3.6 on Ubuntu, running at Core 2 Duo laptop:

$ php isAssocArrayBench.php 10000
Testing method1 (array_values check) - 10000 iterations
  Total time: 4.01563 s
  Average   : 0.02677 ms / test 

Testing method2 (array_keys comparison) - 10000 iterations
  Total time: 12.11279 s
  Average   : 0.08075 ms / test 

Testing method3 (array_filter of keys) - 10000 iterations
  Total time: 16.43639 s
  Average   : 0.10958 ms / test 
@alixaxel

Beware that the fastest method should consume more memory while the GC doesn't kicks in.

@Thinkscape
Owner

@alixaxel That is correct, it will consume a little bit more memory than method 2 - but that's temporary usage per each fn call (per test) and becomes visible only for flat, long arrays (say 1000+ keys).

@fijiwebdesign

Method 3 is what I wanted since it doesn't matter if the array is sequential or not. You can always coerce an array into a sequential one using array_values($array).

I added a method 4 which improves the speed by doing type casting instead of type checking which appears to be much faster.

'method4 (foreach typecast)' =>
        function($array){
            foreach($array as $key => $value) {
                if ($key !== (int) $key) {
                    return true;
                }
            }
            return false;
        },
Testing method1 (array_values check) - 1000 iterations
  Total time: 0.40560 s
  Average   : 0.02704 ms / test

Testing method2 (array_keys comparison) - 1000 iterations
  Total time: 0.57720 s
  Average   : 0.03848 ms / test

Testing method3 (array_filter of keys) - 1000 iterations
  Total time: 5.99041 s
  Average   : 0.39936 ms / test

Testing method4 (foreach typecast) - 1000 iterations
  Total time: 0.54600 s
  Average   : 0.03640 ms / test

Now it is comparable with the first two.

@fijiwebdesign

Also, there is no copying of array keys or values so no extra memory consumption. Especially array_values().

In my case I'm saving arrays to storage and schema depends on array type, The array may have blobs of data several Mb in size. So copying all values would be memory expensive. Instead working with indexed arrays I use foreach() so you don't assume keys are sequential.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.