I'm currently considering the use of Reflection classes (ReflectionClass and ReflectionMethod mainly) in my own MVC web framework, because I need to automatically instanciate controller classes and invoke their methods without any required configuration ("convention over configuration" approach).
I'm concerned about performance, even though I think that database requests are likely to be bigger bottlenecks than the actual PHP code.
So, I'm wondering if anyone has any good or bad experience with PHP 5 Reflection from a performance point of view.
Besides, I'd be curious to know if any one of the popular PHP frameworks (CI, Cake, Symfony, etc.) actually use Reflection.
Basic reflections are quite fast - Reading methods and doc comments for 1000 classes cost just a few milliseconds. Parsing/Autoloading the classfiles does take a lot more time than the actual reflection mechanics.
The term “reflection” in software development means that a program knows its own structure at runtime and can also modify it. This capability is also referred to as “introspection”. In the PHP area, reflection is used to ensure type safety in the program code.
The ReflectionClass::getProperties() function is an inbuilt function in PHP which is used to return an array of the reflected properties. Syntax: ReflectionClass::getProperties($filter) : array. Parameters: This function accepts a parameter filter which helps to remove some of the reflected properties.
ReflectionClass: reports information about a class. ReflectionFunction: reports information about a function. ReflectionParameter: retrieves information about function's or method's parameters.
I benchmarked these 3 options (the other benchmark wasn't splitting CPU cycles and was 4y old):
class foo { public static function bar() { return __METHOD__; } } function directCall() { return foo::bar($_SERVER['REQUEST_TIME']); } function variableCall() { return call_user_func(array('foo', 'bar'), $_SERVER['REQUEST_TIME']); } function reflectedCall() { return (new ReflectionMethod('foo', 'bar'))->invoke(null, $_SERVER['REQUEST_TIME']); }
The absolute time taken for 1,000,000 iterations:
print_r(Benchmark(array('directCall', 'variableCall', 'reflectedCall'), 1000000));
Array ( [directCall] => 4.13348770 [variableCall] => 6.82747173 [reflectedCall] => 8.67534351 )
And the relative time, also with 1,000,000 iterations (separate run):
ph()->Dump(Benchmark(array('directCall', 'variableCall', 'reflectedCall'), 1000000, true));
Array ( [directCall] => 1.00000000 [variableCall] => 1.67164707 [reflectedCall] => 2.13174915 )
It seems that the reflection performance was greatly increased in 5.4.7 (from ~500% down to ~213%).
Here's the Benchmark()
function I used if anyone wants to re-run this benchmark:
function Benchmark($callbacks, $iterations = 100, $relative = false) { set_time_limit(0); if (count($callbacks = array_filter((array) $callbacks, 'is_callable')) > 0) { $result = array_fill_keys($callbacks, 0); $arguments = array_slice(func_get_args(), 3); for ($i = 0; $i < $iterations; ++$i) { foreach ($result as $key => $value) { $value = microtime(true); call_user_func_array($key, $arguments); $result[$key] += microtime(true) - $value; } } asort($result, SORT_NUMERIC); foreach (array_reverse($result) as $key => $value) { if ($relative === true) { $value /= reset($result); } $result[$key] = number_format($value, 8, '.', ''); } return $result; } return false; }
Don't be concerned. Install Xdebug and be sure where the bottleneck is.
There is cost to using reflection, but whether that matters depends on what you're doing. If you implement controller/request dispatcher using Reflection, then it's just one use per request. Absolutely negligible.
If you implement your ORM layer using reflection, use it for every object or even every access to a property, and create hundreds or thousands objects, then it might be costly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With