我一直在浏览laravel源代码,我在callStatic魔术方法中偶然发现了这一点:
switch (count($args)) {
case 0:
return $instance->$method();
case 1:
return $instance->$method($args[0]);
case 2:
return $instance->$method($args[0], $args[1]);
case 3:
return $instance->$method($args[0], $args[1], $args[2]);
case 4:
return $instance->$method($args[0], $args[1], $args[2], $args[3]);
default:
return call_user_func_array([$instance, $method], $args);
}
为什么首先使用switch语句然后使用call_user_func_array()?
答案 0 :(得分:3)
正如克莱夫在评论中有mentioned;这是因为性能问题。
call_user_func_array()
因其性能问题而广为人知。据一些基准测试显示,它比其姐妹函数call_user_func()
慢了 10-20%。
以下是基准测试的结果,用于比较直接通话与动态通话与通过call_user_func*
功能通话的效果:
动态函数调用比直接调用稍慢(前者有一个额外的解释层来确定要调用的函数
call_user_func()
慢约50%,而call_user_func_array()
比直接函数调用慢约100%。静态和常规方法调用大致相当于函数调用 方法调用的
call_user_func()
通常比call_user_func_array()
慢,而更快的操作通常至少需要直接调用执行时间的两倍。
- Matthew Weier O'Phinney
另一位着名的PHP开发人员Paul M. Jones也就完全相同的主题运行了一个基准测试并得出结论:
对
htmlentities()
的原生调用速度是使用对象方法通过call_user_func()
实现同样效果的两倍,使用call_user_func_array()
10-20%强>慢于使用call_user_func()
...显然,PHP必须在幕后做更多工作,以便在使用
call_user_func_array()
时将变量映射到对象和参数。
- Paul M. Jones
最后一件事;从PHP 5.6开始,使用advent参数解包运算符(AKA spread , splat 或 scatter 运算符),您可以安全地使用将该代码重写为:
$instance->$method(...$args);
此外
call_user_func_array
会对性能产生相当大的影响。如果大量的呼叫通过它,这可以产生显着的差异。 出于这个原因,像Laravel和Drupal这样的项目通常会使用switch语句替换特别常见的call_user_func_array
调用。
...
参数解包语法约比call_user_func_args
快3.5到4倍。这解决了性能问题。基准代码和结果。