Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save alcaeus/536156663fac96744eba77b3e133e50a to your computer and use it in GitHub Desktop.
Save alcaeus/536156663fac96744eba77b3e133e50a to your computer and use it in GitHub Desktop.
Performance comparision: in-array vs. isset vs. array_key_exists
<?php declare(strict_types = 1);
function testPerformance($name, Closure $closure, $runs = 1000000)
{
$start = microtime(true);
for (; $runs > 0; $runs--)
{
$closure();
}
$end = microtime(true);
printf("Function call %s took %.5f seconds\n", $name, $end - $start);
}
$items = [1111111];
for ($i = 0; $i < 100000; $i++) {
$items[] = rand(0, 1000000);
}
$items = array_unique($items);
shuffle($items);
$assocItems = array_combine($items, array_fill(0, count($items), true));
$in_array = function () use ($items) {
in_array(1111111, $items);
};
$isset = function () use ($assocItems) {
isset($items[1111111]);
};
$array_key_exists = function () use ($assocItems) {
array_key_exists(1111111, $assocItems);
};
testPerformance('in_array', $in_array, 100000);
testPerformance('isset', $isset, 100000);
testPerformance('array_key_exists', $array_key_exists, 100000);
$ php in_array_vs_isset_vs_array_key_exists.php 
Function call in_array took 1.51871 seconds
Function call isset took 0.14684 seconds
Function call array_key_exists took 0.22123 seconds
@Webist
Copy link

Webist commented May 8, 2021

PHP 8.0.3 (cli)
MacOS 2015
2,7 GHz Dual-Core Intel Core i5
8 GB RAM

class Foo{};  
$foo = new Foo();  
foreach($items as $item){  
    $foo->{$item} = null;  
}  
$property_exists = function () use ($foo) {  
    property_exists($foo, '1111111');  
};
testPerformance('in_array', $in_array, 100000);                // 15.41009 seconds  
testPerformance('isset', $isset, 100000);                      //  0.00544 seconds  
testPerformance('array_key_exists', $array_key_exists, 100000);//  0.00600 seconds  
testPerformance('property_exists', $property_exists, 100000);  //  0.01304 seconds

@faustoFF
Copy link

Guys, you have error in line 29, $items is always NULL.

@JonasKraska
Copy link

Just discussed the topic of this benchmark with a colleague the other day. He pointed out that due to the nature of those data structures you most likely pay for the fast lookup with disadvantages in time and memory needed to build the data structure in the first place (like @michaelbutler mentioned before). So its highly comes down to very specific use cases (read vs write heavy access operations) to capitalize of the differences suggested by this benchmark. To bring numbers to the table I measured the time an memory needed to build the generic item array vs. the associative version in a comparable fashion:

PHP 8.0.14 (cli)
MacOS 11.4
2,6 GHz 6-Core Intel Core i7
32 GB 2667 MHz DDR4

Time used to build the item array: 0.00682 seconds
Memory used for item array: 4198480 bytes
Time used to build the associative item array: 0.01031 seconds (1.48 %)
Memory used for associative item array: 5242960 bytes (1.25 %)

Function call in_array took 3.74565 seconds
Function call isset took 0.04157 seconds
Function call array_key_exists took 0.04312 seconds

Code for reference (quick and dirty):

// ...

$base = [1111111];
for ($i = 0; $i < 100000; $i++) {
    $base[] = rand(0, 1000000);
}
$base = array_unique($base);
shuffle($base);

$startMemItems = memory_get_usage(true);
$startTimeItems = microtime(true);
$items = [];
foreach ($base as $k => $v) {
    $items[] = $v;
}
$endTimeItems = microtime(true);
$endMemItems = memory_get_usage(true);

printf("Time used to build the item array: %.5f seconds\n", $endTimeItems - $startTimeItems);
printf("Memory used for item array: %d bytes\n", $endMemItems - $startMemItems);

$startMemAssocItems = memory_get_usage(true);
$startTimeAssocItems = microtime(true);
$assocItems = [];
foreach ($base as $k => $v) {
    $assocItems[$v] = true;
}
$endTimeAssocItems = microtime(true);
$endMemAssocItems = memory_get_usage(true);

printf(
    "Time used to build the associative item array: %.5f seconds (%.2f %%)\n",
    $endTimeAssocItems - $startTimeAssocItems,
    ($endTimeAssocItems - $startTimeAssocItems) / ($endTimeItems - $startTimeItems)
);
printf(
    "Memory used for associative item array: %d bytes (%.2f %%)\n",
    $endMemAssocItems - $startMemAssocItems,
    ($endMemAssocItems - $startMemAssocItems) / ($endMemItems - $startMemItems)
);

// ...

@AnrDaemon
Copy link

This comes down to what you have on hand.
If you have a static structure you compare against (i.e. filtering out sensitive content before passing data to the client), you have a map in code prepared for fastest possible lookup.
When you have an unknown data to search for keys of interest, it's most likely not worth rebuilding it as that сould cost more than what you can save on lookup itself.
So, choose wisely!

@klc
Copy link

klc commented Jul 3, 2024

PHP Version 8.3.7 (cli)
MacOS 14.5
Apple M1 Pro 16GB

Run #1

Function call in_array took 4.55296 seconds
Function call isset took 0.00325 seconds
Function call array_key_exists took 0.00316 seconds

Run #2

Function call in_array took 2.22286 seconds
Function call isset took 0.00329 seconds
Function call array_key_exists took 0.00327 seconds

Run #3


Function call in_array took 2.20876 seconds
Function call isset took 0.00315 seconds
Function call array_key_exists took 0.00303 seconds

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