Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP 5 Reflection API performance

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.

like image 599
Franck Avatar asked Nov 16 '08 23:11

Franck


People also ask

Is PHP reflection slow?

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.

Does PHP have reflection?

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.

What is reflection class PHP?

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.

What is ReflectionClass in laravel?

ReflectionClass: reports information about a class. ReflectionFunction: reports information about a function. ReflectionParameter: retrieves information about function's or method's parameters.


2 Answers

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; } 
like image 143
Alix Axel Avatar answered Sep 23 '22 17:09

Alix Axel


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.

like image 31
Kornel Avatar answered Sep 20 '22 17:09

Kornel