Skip to content

Instantly share code, notes, and snippets.

@weierophinney
Forked from prolic/test.php
Created July 11, 2012 19:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save weierophinney/3092671 to your computer and use it in GitHub Desktop.
Save weierophinney/3092671 to your computer and use it in GitHub Desktop.
performance test on different isSubclassOf implementations
<?php
// our test cases
interface A {}
class B implements A {}
class C extends B {}
class D {}
class IsSubclassOf
{
// Suggested by ralphschindler
public static function uncachedUsingClassImplementsInsensitive($className, $type)
{
$parents = class_parents($className, true) + class_implements($className, true);
return (isset($parents[$type]));
}
// Suggested by ralphschindler
public static function uncachedUsingClassImplements($className, $type)
{
$parents = array_change_key_case(class_parents($className, true) + class_implements($className, true), CASE_LOWER);
return (isset($parents[strtolower($type)]));
}
// Implementation similar to what is currently in DI
public static function cachedUsingClassImplements($className, $type)
{
$className = ltrim($className, '\\');
$type = ltrim($type, '\\');
static $isSubclassFuncCache = null; // null as unset, array when set
if ($isSubclassFuncCache === null) {
$isSubclassFuncCache = array();
}
$caseInsensitiveParent = strtolower($className);
if (!array_key_exists($caseInsensitiveParent, $isSubclassFuncCache)) {
$parents = class_parents($className, true) + class_implements($className, true);
$isSubclassFuncCache[$caseInsensitiveParent] = array_change_key_case($parents, CASE_LOWER);
}
return (isset($isSubclassFuncCache[$caseInsensitiveParent][strtolower($type)]));
}
// reflection implementation, uses no cache at all
public static function uncachedReflection($className, $type)
{
if (is_subclass_of($className, $type)) {
return true;
}
if (!interface_exists($type)) {
return false;
}
$r = new ReflectionClass($className);
return $r->implementsInterface($type);
}
// reflection implementation, using cache, too
public static function cachedReflection($className, $type)
{
if (is_subclass_of($className, $type)) {
return true;
}
if (!interface_exists($type)) {
return false;
}
static $isSubclassFuncCache = null; // null as unset, array when set
if ($isSubclassFuncCache === null) {
$isSubclassFuncCache = array();
}
$caseInsensitiveParent = strtolower($className);
$caseInsensitiveChild = strtolower($type);
if (!array_key_exists($caseInsensitiveParent, $isSubclassFuncCache)) {
$r = new ReflectionClass($className);
if ($r->implementsInterface($type)) {
$isSubclassFuncCache[$caseInsensitiveParent][$caseInsensitiveChild] = true;
}
}
return (isset($isSubclassFuncCache[$caseInsensitiveParent][$caseInsensitiveChild]));
}
}
$i = new IsSubclassOf();
echo "Non-static, uncached, using class_implements, case insensitive\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
$i->uncachedUsingClassImplementsInsensitive('B', 'A');
$i->uncachedUsingClassImplementsInsensitive('C', 'A');
$i->uncachedUsingClassImplementsInsensitive('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
echo "Non-static, uncached, using class_implements, case sensitive\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
$i->uncachedUsingClassImplements('B', 'A');
$i->uncachedUsingClassImplements('C', 'A');
$i->uncachedUsingClassImplements('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
echo "Non-static, cached, using class_implements\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
$i->cachedUsingClassImplements('B', 'A');
$i->cachedUsingClassImplements('C', 'A');
$i->cachedUsingClassImplements('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
echo "Non-static, uncached, using reflection\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
$i->uncachedReflection('B', 'A');
$i->uncachedReflection('C', 'A');
$i->uncachedReflection('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
echo "Non-static, cached, using reflection\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
$i->cachedReflection('B', 'A');
$i->cachedReflection('C', 'A');
$i->cachedReflection('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
echo "Static, uncached, using class_implements, case insensitive\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
IsSubclassOf::uncachedUsingClassImplementsInsensitive('B', 'A');
IsSubclassOf::uncachedUsingClassImplementsInsensitive('C', 'A');
IsSubclassOf::uncachedUsingClassImplementsInsensitive('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
echo "Static, uncached, using class_implements, case sensitive\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
IsSubclassOf::uncachedUsingClassImplements('B', 'A');
IsSubclassOf::uncachedUsingClassImplements('C', 'A');
IsSubclassOf::uncachedUsingClassImplements('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
echo "Static, cached, using class_implements\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
IsSubclassOf::cachedUsingClassImplements('B', 'A');
IsSubclassOf::cachedUsingClassImplements('C', 'A');
IsSubclassOf::cachedUsingClassImplements('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
echo "Static, uncached, using reflection\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
IsSubclassOf::uncachedReflection('B', 'A');
IsSubclassOf::uncachedReflection('C', 'A');
IsSubclassOf::uncachedReflection('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
echo "Static, cached, using reflection\n";
$s = microtime(true);
for ($j = 0; $j < 500000; $j++ ) {
IsSubclassOf::cachedReflection('B', 'A');
IsSubclassOf::cachedReflection('C', 'A');
IsSubclassOf::cachedReflection('D', 'A');
}
$e = microtime(true);
echo ' ' . ($e - $s) . PHP_EOL;
// Results:
// Non-static, uncached, using class_implements, case insensitive
// 5.8243050575256
// Non-static, uncached, using class_implements, case sensitive
// 7.9895088672638
// Non-static, cached, using class_implements
// 11.565550804138
// Non-static, uncached, using reflection
// 5.8287949562073
// Non-static, cached, using reflection
// 10.351413965225
// Static, uncached, using class_implements, case insensitive
// 5.8487641811371
// Static, uncached, using class_implements, case sensitive
// 7.9592990875244
// Static, cached, using class_implements
// 11.568488121033
// Static, uncached, using reflection
// 5.8595230579376
// Static, cached, using reflection
// 10.408411026001
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment