The Fastest PHP Function to Check if a Value Exists in an Array. isset vs array_search vs in_array vs other methods

/ Updated on January 25, 2023 / PHP /
  • 4.1 out of 5 Stars

In this article, we are going to find out the fastest PHP function that is used to check if an array contains a value. We will test and compare the performance of five different methods. We will analyze how the parameter $strict affects the performance of array_search and in_array. And finally, we will compare the results with and without OPcache enabled, and draw conclusions, which method is better.

PHP Performance

How we will test

We will look for a presence of a specific search string in a simple one-dimensional non-associative array of strings. We will perform our tests on three input arrays of different sizes (100, 1000 and 10,000 elements) to see if performance of these methods degrade with increasing number of elements.

To make our results more independent on current server load, we'll perform 3 passes for 100,000 iterations for every search method.

In order to check how the performance is affected by OPCache, we run our testing script twice: with OPcache disabled and with OPCache enabled. We disable OPcache for the testing script by adding its path into the OPcache blacklist.

Functions we compare

Here is a list of all array searching methods we'll compare (if there is something not on the list, write in comment):

As we have a non-associative array of values as our source, for some methods like isset we'll need to convert it to the associative array. We'll do it with the array_flip function, which execution time is also added to the the total time of the method.

Our test environment

Server with the Intel Xeon E3 1270 V3 CPU running PHP 7.3.24.

Results with OPcache disabled

Array size: 100, 3 passes of 100,000 iterations

MethodTotal time, seconds* Preparation time, secondsOperations/s
isset0.00654790.000016245,929,742
null coalescing0.0088511 +35%0.000006933,920,776 -26%
array_search0.1349378 +1,425%02,223,247 -93%
in_array0.1424952 +6%02,105,335 -5%
error suppression0.1596813 +12%0.00000931,878,851 -11%
array_search strict0.1943438 +22%01,543,656 -18%
in_array strict0.1973531 +2%01,520,118 -2%

Array size: 1000, 3 passes of 100,000 iterations

MethodTotal time, seconds* Preparation time, secondsOperations/s
isset0.00645710.000105147,229,607
null coalescing0.0086432 +34%0.000058234,944,768 -26%
error suppression0.1587451 +1,737%0.00006411,890,587 -95%
array_search1.3462260 +748%0222,845 -88%
in_array1.4144890 +5%0212,091 -5%
array_search strict1.8396320 +30%0163,076 -23%
in_array strict1.8466282 +0%0162,458 -0%

Array size: 10000, 3 passes of 100,000 iterations

MethodTotal time, seconds* Preparation time, secondsOperations/s
isset0.00738120.000979246,860,241
null coalescing0.0096066 +30%0.000621833,389,709 -29%
error suppression0.1587968 +1,553%0.00061961,896,608 -94%
in_array14.8727291 +9,266%020,171 -99%
array_search15.0306778 +1%019,959 -1%
in_array strict18.9210389 +26%015,855 -21%
array_search strict19.1551011 +1%015,662 -1%

* For the "isset", "null coalescing" and "error suppression" methods the total time includes time of array_flip call to prepare data.

Results with OPcache enabled

Array size: 100, 3 passes of 100,000 iterations

MethodTotal time, seconds* Preparation time, secondsOperations/s
isset0.00580020.000019151,892,577
null coalescing0.0078719 +36%0.000006038,139,282 -27%
array_search0.1314380 +1,570%02,282,445 -94%
in_array0.1400669 +7%02,141,834 -6%
error suppression0.1493380 +7%0.00000812,008,975 -6%
in_array strict0.1880350 +26%01,595,448 -21%
array_search strict0.1889241 +0%01,587,940 -0%

Array size: 1000, 3 passes of 100,000 iterations

MethodTotal time, seconds* Preparation time, secondsOperations/s
isset0.00578380.000126853,032,039
null coalescing0.0078449 +36%0.000067238,571,859 -27%
error suppression0.1482992 +1,790%0.00006482,023,822 -95%
array_search1.3640051 +820%0219,941 -89%
in_array1.4514329 +6%0206,692 -6%
array_search strict1.8645689 +28%0160,895 -22%
in_array strict1.8645763 +0%0160,894 -0%

Array size: 10000, 3 passes of 100,000 iterations

MethodTotal time, seconds* Preparation time, secondsOperations/s
isset0.00688200.001196952,769,604
null coalescing0.0087378 +27%0.000865738,109,250 -28%
error suppression0.1490369 +1,606%0.00089912,025,141 -95%
in_array15.0471058 +9,996%019,937 -99%
array_search15.2325349 +1%019,695 -1%
in_array strict19.2085185 +26%015,618 -21%
array_search strict19.3677390 +1%015,490 -1%

* For the "isset", "null coalescing" and "error suppression" methods the total time includes time of array_flip call to prepare data.

Analysis of results

As we can see, PHP today is a very capable language. Every function that we tested runs very fast, performing millions of calls per second. This means that you don't need to rewrite your code if you have a few calls of any of these functions. But, if your script performs thousands of array searches, it is preferable to use the most performance-efficient method.

Looking at the results, we can say that:

  • isset is a clear winner here. Even with the additional array_flip call (our input array was a non-associative one) it is faster than specialized array search functions.

  • Checking array value by key with the null coalescing operator ($arr[$needle] ?? 0) has a bit slower performance because of the overhead on accessing actual value. But this function is a life-saver if you need to check if key exists and get the value at the same time.
  • The performance of array_search is acceptable on smaller arrays and drastically drops with increasing array size.
  • array_search seems to be a slightly faster than in_array on smaller arrays, but for an array with 10,000 elements we can see that they are on par.
  • The array_search and in_array with $strict = true parameter are the slowest methods in our test. This parameter enables a strict type comparison of each element and consumes an additional time. Do not use it unless necessary.
  • The "silence" or "shut-op" operator @ should be avoided too. Although this method is faster than array_search and in_array on larger arrays, getting an array value by key if this key is not exists is about 20 times slower with this method than with the null coalescing operator.

The impact of array size

The search array size has almost no impact on the performance of functions that access values by key (isset, null coalescing operator). On the other hand, we see a huge drop of perfomance of array_search and in_array on larger arrays.

The impact of OPcache

OPcache gives a performance gain of about 13% for isset and has almost no influence on the results of array_search and in_array functions.

Test script code


<?php
 error_reporting(E_ALL);
 set_time_limit(300); //5 min
 //nocache
 header('X-Accel-Buffering: no');
 header("Cache-Control: private");
?>

<html>
<head>
<style>
.results > table th
{
text-align:left;
font-weight: normal;
background: #ddd;
}

.results > table, .results > table td, .results > table th
{
border:1px solid #e7e7e7;
border-collapse:collapse;
margin:0;
padding:0;
}

.results > table td, .results > table th
{
 padding: 10px;
}
</style>

<title>Performance test for array search</title></head><body>

<?php

 echo date('r').', PHP: '.PHP_VERSION.', OS: '.(defined('PHP_OS_FAMILY') ? PHP_OS_FAMILY : PHP_OS).', ';
 $opstatus = function_exists('opcache_get_status') ? opcache_get_status() : 0;
 if ($opstatus)
  if (!isset($opstatus['scripts'][__FILE__]))
   $opstatus = 0;
 if ($opstatus)
  echo 'OPcache enabled';
 else
  echo 'OPcache disabled';
 echo "<hr>\r\n<div class=\"results\">";

 $passes = 3;
 $array_sizes = [100,1000,10000];
 $icount = 100000;

 $tests = ['array_search','array_search strict','in_array','in_array strict',
 'isset','error suppression','null coalescing'];
 $needle = 'abcd123';

 $preparetimes = [];
 $times = [];
 $fliptime = [];

 for ($n = 0; $n < $passes; $n++)
 {
  foreach ($array_sizes as $asize)
  {
   $arr = [];
   for ($i = 0; $i < $asize; $i++)
    $arr[] = sprintf('%04x',rand(0,0xfffffff));

   foreach ($tests as $test)
   {
    $starttime = microtime(true);
    $preparetime = 0;
    $f = str_replace(' ','_',$test).'_Test';
    call_user_func($f);
    $times[$asize][$test][] = microtime(true) - $starttime;
    if ($preparetime)
     $preparetimes[$asize][$test][] = $preparetime - $starttime;
   }
  }
 }

 //calc total time
 foreach ($times as $asize=>&$tests)
  foreach ($tests as &$results)
   $results = array_sum($results);
 unset($tests, $results);

 foreach ($preparetimes as $asize=>&$tests)
  foreach ($tests as &$results)
   $results = array_sum($results);
 unset($tests,$results);

 //display results
 foreach ($times as $asize=>$tests)
 {
  asort($tests);
  $s = '';
  $prevtime = 0;
  $prevops = 0;
  foreach ($tests as $n=>$t)
  {
   $preparetime = $preparetimes[$asize][$n] ?? 0;

   $timediff = !$prevtime ? '' : ' <sup style="color:red">+'.number_format(($t-$prevtime)/$prevtime*100).'%</sup>';
   $optime = $t - $preparetime;
   $ops = $passes*$icount/$optime;
   $opsdiff = !$prevops ? '' : ' <sup style="color:red">-'.number_format(($prevops-$ops)/$prevops*100).'%</sup>';

   if ($preparetime)
    $preparetime = number_format($preparetime,7);

   $s .= "<tr><td>$n</td><td>".number_format($t,7).$timediff.
   "</td><td>$preparetime</td><td>".number_format($ops).$opsdiff.'</td></tr>';
   $prevtime = $t;
   $prevops = $ops;
  }
  echo "<h3>Array size: $asize, $passes passes of ".number_format($icount)." iterations</h3>
  <table><tr><th>Method</th><th>Total time, seconds*</th>
  <th>Preparation time, seconds</th><th>Operations/s</th></tr>$s</table>\r\n";
 }

 echo '<p>* For the "isset", "null coalescing" and "error suppression" methods the total time includes time of <samp>array_flip</samp> call to prepare data.</p>';

 function array_search_Test()
 {
  global $arr, $icount, $needle;

  $c = 0;
  for ($i = 0; $i < $icount; $i++)
   if (array_search($needle,$arr))
    $c++;

  return $c;
 }

 function array_search_strict_Test()
 {
  global $arr, $icount, $needle;

  $c = 0;
  for ($i = 0; $i < $icount; $i++)
   if (array_search($needle,$arr,true))
    $c++;

  return $c;
 }


 function in_array_Test()
 {
  global $arr, $icount, $needle;

  $c = 0;
  for ($i = 0; $i < $icount; $i++)
   if (in_array($needle,$arr))
    $c++;

  return $c;
 }

 function in_array_strict_Test()
 {
  global $arr, $icount, $needle;

  $c = 0;
  for ($i = 0; $i < $icount; $i++)
   if (in_array($needle,$arr,true))
    $c++;

  return $c;
 }

 function isset_Test()
 {
  global $arr, $icount, $needle, $preparetime;

  $newarr = array_flip($arr);
  $preparetime = microtime(true);

  $c = 0;
  for ($i = 0; $i < $icount; $i++)
   if (isset($newarr[$needle]))
    $c++;

  return $c;
 }

 function error_suppression_Test()
 {
  global $arr, $icount, $needle, $preparetime;

  $newarr = array_flip($arr);
  $preparetime = microtime(true);

  $c = 0;
  for ($i = 0; $i < $icount; $i++)
   if (@$newarr[$needle] !== null)
    $c++;

  return $c;
 }


 function null_coalescing_Test()
 {
  global $arr, $icount, $needle, $preparetime;

  $newarr = array_flip($arr);
  $preparetime = microtime(true);

  $c = 0;
  for ($i = 0; $i < $icount; $i++)
   if ($newarr[$needle] ?? null !== null)
    $c++;

  return $c;
 }

?>

</div></body></html>

Conclusion

All of the reviewed methods are really fast resulting in millions operations per second. This means that you don't need to do any excessive optimization if your array search ratio is low. If you have a few calls to array_search or in_array and your arrays are small, never mind.

On the other hand, If your scripts perform a large amount of array searching and accessing operations or your arrays consist of thousands of elements, consider switching to associative arrays and isset or null coalescing operator, as they are the clear winners of this performance competition.

Rate This Article

How would you rate the quality of this content?
Currently rated: 4.1 out of 5 stars. 9 users have rated this article. Select your rating:
  • 4.1 out of 5 Stars
  • 1
  • 2
  • 3
  • 4
  • 5

About The Author

Lembit Kuzin is a software developer from Estonia. He is passionate about new technologies, web development and search engine optimization. He has over 10 years of webdev experience and now writes exclusive articles for Webmaster Tips.