我目前正在考虑在我自己的MVC Web框架中使用Reflection类(主要是ReflectionClass和ReflectionMethod),因为我需要自动实例化控制器类并调用他们的方法而不需要任何必需的配置("约定优于配置"方法).
我担心性能,即使我认为数据库请求可能是比实际PHP代码更大的瓶颈.
所以,我想知道从性能的角度来看,是否有人对PHP 5 Reflection有任何好的或坏的体验.
此外,我很想知道任何一个流行的PHP框架(CI,Cake,Symfony等)是否实际使用Reflection.
我对这3个选项进行了基准测试(另一个基准测试不是拆分CPU周期,而是4年前):
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']); }
1,000,000次迭代所需的绝对时间:
print_r(Benchmark(array('directCall','variableCall','reflectCall'),1000000));
Array ( [directCall] => 4.13348770 [variableCall] => 6.82747173 [reflectedCall] => 8.67534351 )
相对时间,也有1,000,000次迭代(单独运行):
ph() - >转储(Benchmark(array('directCall','variableCall','reflectCall'),1000000,true));
Array ( [directCall] => 1.00000000 [variableCall] => 1.67164707 [reflectedCall] => 2.13174915 )
似乎反射性能在5.4.7(从~500%下降到~213%)大大增加.
这是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; }
不要担心.安装Xdebug并确保瓶颈在哪里.
使用反射需要花费成本,但这是否重要取决于您正在做什么.如果使用Reflection实现控制器/请求调度程序,那么每个请求只使用一次.绝对可以忽略不计.
如果使用反射实现ORM层,则将其用于每个对象甚至每次访问属性,并创建数百或数千个对象,然后它可能成本很高.
在我的机器上调用静态功能100万次将花费约0.31秒.使用ReflectionMethod时,它的成本约为1.82秒.这意味着使用Reflection API的成本要高出约500%.
这是我使用的代码:
invokeArgs(null, array('f')); } echo ($b=microtime(true) - $s)."\n"; echo 100/$a*$b;
显然,实际影响取决于您希望进行的呼叫次数
此外,我很想知道任何一个流行的PHP框架(CI,Cake,Symfony等)是否实际使用Reflection.
http://framework.zend.com/manual/en/zend.server.reflection.html
"通常,此功能仅供框架的服务器类开发人员使用."