Skip to content

Instantly share code, notes, and snippets.

@Thinkscape
Created March 3, 2012 11:35
Show Gist options
  • Save Thinkscape/1965669 to your computer and use it in GitHub Desktop.
Save Thinkscape/1965669 to your computer and use it in GitHub Desktop.
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";
}
@funder7
Copy link

funder7 commented Jan 15, 2022

check this out:

$methods = [
 
    // [...]

    'method4 (revision of method1, with php8.1 fn)' =>
       function ($array) {
            return (array_is_list($array) === false);
        },

    'method5 (json_encode output parsing with array_is_list - php>=8.1)' =>
       static function ($array) {
            // consider empty, and [0, 1, 2, ...] sequential
            if (empty($array) || array_is_list($array)) {
                return false;
            }

            // first scenario:
            // [  1  => [*any*] ]
            // [ 'a' => [*any*] ]
            foreach ( $array as $key => $value ) {
                if (is_array($value)) {
                    return true;
                }
            }

            // second scenario: read the json string
            $jsonNest = json_encode($array, JSON_THROW_ON_ERROR);

            return str_contains($jsonNest, '{');
        },


    'method6 (json_encode output parsing - php=8.0)' =>
       static function ($array) {

            if (empty($array) || array_values($array) !== $array) { return false; }

            foreach ( $array as $key => $value ) { if (is_array($value)) { return true; } }
            
            $jsonNest = json_encode($array, JSON_THROW_ON_ERROR);

            return str_contains($jsonNest, '{');
        },

];

Results

Testing method1 (array_values check) - 10000 iterations
  Total time: 0.60444 s
  Average   : 0.00403 ms / test 

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

Testing method3 (array_filter of keys) - 10000 iterations
  Total time: 2.22523 s
  Average   : 0.01483 ms / test 

Testing method4 (revision of method1, with php8.1 fn) - 10000 iterations
  Total time: 0.09834 s
  Average   : 0.00066 ms / test 

Testing method5 (json_encode output parsing with array_is_list - php>=8.1) - 10000 iterations
  Total time: 0.47469 s
  Average   : 0.00316 ms / test

Testing method6 (json_encode output parsing - php<=8.0) - 10000 iterations
  Total time: 1.01134 s
  Average   : 0.00674 ms / test 

Anyone curious about the benchmark without the static closure?

Testing method5 (json_encode output parsing with array_is_list - php>=8.1) - 10000 iterations
  Total time: 1.08914 s
  Average   : 0.00726 ms / test 

Testing method6 (json_encode output parsing - php=8.0) - 10000 iterations
  Total time: 4.92953 s
  Average   : 0.03286 ms / test 

They are much slower!

other methods perform the same instead. Somebody can explain me why?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment