Last active
December 19, 2015 17:19
-
-
Save lopopolo/5990592 to your computer and use it in GitHub Desktop.
microbenchmark for lookup performance in arrays and objects in PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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