Skip to content

Instantly share code, notes, and snippets.

@lopopolo
Last active December 19, 2015 17:19
Show Gist options
  • Save lopopolo/5990592 to your computer and use it in GitHub Desktop.
Save lopopolo/5990592 to your computer and use it in GitHub Desktop.
microbenchmark for lookup performance in arrays and objects in PHP
<?php
# vim: sw=2 ts=2
echo 'PHP version: ' . phpversion() . PHP_EOL;
function lookup_ake(array $a, $key, $default = null)
{
if (array_key_exists($key, $a))
{
return $a[$key];
}
return $default;
}
function lookup_isset(array $a, $key, $default = null)
{
if (isset($a[$key]))
{
return $a[$key];
}
return $default;
}
class AA implements ArrayAccess
{
private $keys = array('existing_key' => 1, 'unset_key' => 1);
public $existing_key = 1;
public $unset_key = null;
public function offsetExists($offset)
{
return isset($this->keys[$offset]);
}
public function offsetGet($offset)
{
return isset($this->$offset) ? $this->$offset : null;
}
public function offsetSet($offset, $value)
{
$this->$offset = $value;
$this->keys[$offset] = 1;
}
public function offsetUnset($offset)
{
$this->$offset = null;
unset($this->keys[$offset]);
}
}
class ArrayBackedAA implements ArrayAccess
{
private $array = array('existing_key' => 1, 'unset_key' => null);
public function offsetExists($offset)
{
return isset($this->array[$offset]);
}
public function offsetGet($offset)
{
return isset($this->array[$offset]) ? $this->array[$offset] : null;
}
public function offsetSet($offset, $value)
{
$this->array[$offset] = $value;
}
public function offsetUnset($offset)
{
unset($this->array[$offset]);
}
}
// array keys
$existing_key = 'existing_key';
$unset_key = 'unset_key';
$non_existing_key = 'non_existing_key';
$keys = array($existing_key, $unset_key, $non_existing_key);
// Arrays to lookup in
$array = array($existing_key => 1, $unset_key => null);
$array_access_obj = new AA();
$array_backed_aa_obj = new ArrayBackedAA();
$default = null;
define('ITERATIONS', 1000000);
/////////////////////
// Raw array lookup
error_reporting(E_ALL & ~E_STRICT & ~E_NOTICE);
foreach ($keys as $key)
{
$start = microtime(true);
for ($i = 0; $i < ITERATIONS; ++$i)
{
$value = $array[$key];
}
$stop = microtime(true);
echo "Unsafe and non-E_STRICT-compliant lookup for key $key:\n\t" . number_format($stop - $start, 8) . PHP_EOL;
}
error_reporting(E_ALL | E_STRICT | E_NOTICE);
//////////////////
// inlined tests
foreach ($keys as $key)
{
$start = microtime(true);
for ($i = 0; $i < ITERATIONS; ++$i)
{
$value = $default;
if (isset($array[$key]))
{
$value = $array[$key];
}
}
$stop = microtime(true);
echo "Inlined lookup using isset and key $key:\n\t" . number_format($stop - $start, 8) . PHP_EOL;
}
foreach ($keys as $key)
{
$start = microtime(true);
for ($i = 0; $i < ITERATIONS; ++$i)
{
$value = $default;
if (array_key_exists($key, $array))
{
$value = $array[$key];
}
}
$stop = microtime(true);
echo "Inlined lookup using array_key_exists and key $key:\n\t" . number_format($stop - $start, 8) . PHP_EOL;
}
//////////////////////
// Lookup functions
foreach (array('lookup_isset', 'lookup_ake') as $function)
{
foreach ($keys as $key)
{
$start = microtime(true);
for ($i = 0; $i < ITERATIONS; ++$i)
{
$value = $function($array, $key);
}
$stop = microtime(true);
echo "Lookup function '$function' and key $key:\n\t" .
number_format($stop - $start, 8) . PHP_EOL;
}
}
////////////////////////
// Array access objects
foreach (array($array_access_obj, $array_backed_aa_obj) as $array_access)
{
foreach ($keys as $key)
{
$start = microtime(true);
for ($i = 0; $i < ITERATIONS; ++$i)
{
$value = $array_access[$key];
}
$stop = microtime(true);
echo "ArrayAccess " . get_class($array_access) . " and key $key:\n\t" .
number_format($stop - $start, 8) . PHP_EOL;
}
}
////////////////////
// Property access
foreach ($keys as $key)
{
if ($key === $non_existing_key) continue;
$start = microtime(true);
for ($i = 0; $i < ITERATIONS; ++$i)
{
$value = $array_access_obj->$key;
}
$stop = microtime(true);
echo "Class property get " . get_class($array_access_obj) . " and key $key:\n\t" .
number_format($stop - $start, 8) . PHP_EOL;
}
PHP version: 5.4.16
Unsafe and non-E_STRICT-compliant lookup for key existing_key:
0.06961894
Unsafe and non-E_STRICT-compliant lookup for key unset_key:
0.06871915
Unsafe and non-E_STRICT-compliant lookup for key non_existing_key:
0.55242419
Inlined lookup using isset and key existing_key:
0.10207295
Inlined lookup using isset and key unset_key:
0.06304383
Inlined lookup using isset and key non_existing_key:
0.06005597
Inlined lookup using array_key_exists and key existing_key:
0.24598002
Inlined lookup using array_key_exists and key unset_key:
0.24059892
Inlined lookup using array_key_exists and key non_existing_key:
0.20083094
Lookup function 'lookup_isset' and key existing_key:
0.41206813
Lookup function 'lookup_isset' and key unset_key:
0.38659596
Lookup function 'lookup_isset' and key non_existing_key:
0.40835810
Lookup function 'lookup_ake' and key existing_key:
0.53824496
Lookup function 'lookup_ake' and key unset_key:
0.53453398
Lookup function 'lookup_ake' and key non_existing_key:
0.52240610
ArrayAccess AA and key existing_key:
0.31920791
ArrayAccess AA and key unset_key:
0.29070306
ArrayAccess AA and key non_existing_key:
0.28701401
ArrayAccess ArrayBackedAA and key existing_key:
0.35205817
ArrayAccess ArrayBackedAA and key unset_key:
0.29902601
ArrayAccess ArrayBackedAA and key non_existing_key:
0.28959703
Class property get AA and key existing_key:
0.07733297
Class property get AA and key unset_key:
0.07042480
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment