【php】PHP 的 call_user_func_array 方法是否效率很低?
Laravel 5.1
的 Facade
类 的 __callStatic
方法代码如下:
public static function __callStatic($method, $args){
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
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);
}
}
为什么不直接写成:
public static function __callStatic($method, $args){
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
return call_user_func_array([$instance, $method], $args);
}
回答
答:call_user_func_array
效率偏低。
基准测试如下
对比范围
直接调用
变量函数调用
call_user_func
调用call_user_func_array
调用
测试结果
我们可以看到,call_user_func_array
所用时间为:1.1608240604401s
测试过程
测试代码如下:
<?phperror_reporting(E_ALL | E_STRICT);
define('ITERATIONS', 2000000);
class Bench
{
private $bench_name;
private $start_time;
private $end_time;
public function start($name)
{
$this->bench_name = $name;
$this->start_time = microtime(true);
}
public function end()
{
$this->end_time = microtime(true);
echo "Call style: " . $this->bench_name . '; ' . ($this->end_time - $this->start_time) . " seconds". PHP_EOL;
}
}
class Test
{
public function test($a, $b, $c)
{
return;
}
}
$bench = new Bench();
$test = new Test();
$arg = [1, 2, 3];
$func_name = 'test';
$bench->start('normal');
for ($i=0; $i < ITERATIONS; ++$i) {
$test->test($arg[0], $arg[1], $arg[2]);
}
$bench->end();
$bench->start('var_function');
for ($i=0; $i < ITERATIONS; ++$i) {
$test->$func_name($arg[0], $arg[1], $arg[2]);
}
$bench->end();
$bench->start('call_user_func');
for ($i=0; $i < ITERATIONS; ++$i) {
call_user_func([$test, $func_name], $arg[0], $arg[1], $arg[2]);
}
$bench->end();
$bench->start('call_user_func_array');
for ($i=0; $i < ITERATIONS; ++$i) {
call_user_func_array([$test, $func_name], $arg);
}
$bench->end();
题主是不是看错了或者看的是修改过的源码,原始laravel中并没有发现存在这些代码,能否标出具体的laravel版本和文件路径
我看到的laravel的 Facade 类中代码是这样的
/** * Handle dynamic, static calls to the object.
*
* @param string $method
* @param array $args
* @return mixed
*
* @throws \RuntimeException
*/
public static function __callStatic($method, $args)
{
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
return $instance->$method(...$args);
}
这问题我也纳闷. mark, 看会不会遇到能解答这个问题的人.
我刚刚创建了一个laravel的项目
"laravel/framework": "5.5.*"
然后看了源码:
/** * Handle dynamic, static calls to the object.
*
* @param string $method
* @param array $args
* @return mixed
*
* @throws \RuntimeException
*/
public static function __callStatic($method, $args)
{
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
return $instance->$method(...$args);
}
额 题主是什么版本的啊? 感觉跟楼上就几个同学看到的一样啊
三个...不定参数的写法是php 5.6版本才有的新特性,我猜可能框架5.1版本的时候还没支持php新特性的吧
光看题主的问题, php 中的 call_user_func_array()
并不慢, 相反这个比普通的函数执行更快, 因为这个在 php7 添加为语言结构(其他语言结构, 比如 echo), 这个信息可以从鸟哥的博客获取到.
另外 laravel 中 facade 中多这样一层封装, 其实是使用 __callStatic()
函数实现, 这个稍微会有一点性能损失.
Iterations: 100 000
Averaged over: 10
PHP 5.6.30 (cli) (built: Jan 18 2017 19:47:28)
Overall Average | |||
---|---|---|---|
Invocation | Time (s) | Delta (s) | % |
directFunction | 0.0089 | -0.0211 | -70.19 |
directStatic | 0.0098 | -0.0202 | -67.39 |
directLambda | 0.0109 | -0.0191 | -63.52 |
directInstance | 0.0116 | -0.0184 | -61.31 |
directClosure | 0.0150 | -0.0150 | -50.15 |
Invoke | 0.0282 | -0.0018 | -6.13 |
call_user_func | 0.0300 | ||
ClosureFactory | 0.0316 | +0.0016 | +5.20 |
assignedClosureFactory | 0.0328 | +0.0028 | +9.28 |
call_user_func_array | 0.0399 | +0.0099 | +33.02 |
InvokeCallUserFunc | 0.0418 | +0.0118 | +39.17 |
directImplementation | 0.0475 | +0.0175 | +58.28 |
Iterations: 100 000
Averaged over: 10
PHP 7.1.2 (cli) (built: Feb 14 2017 21:24:45)
Overall Average | |||
---|---|---|---|
Invocation | Time (s) | Delta (s) | % |
directFunction | 0.0043 | -0.0096 | -68.92 |
directStatic | 0.0050 | -0.0089 | -64.04 |
directInstance | 0.0058 | -0.0081 | -58.22 |
directLambda | 0.0063 | -0.0075 | -54.44 |
directClosure | 0.0081 | -0.0058 | -41.57 |
call_user_func | 0.0139 | ||
call_user_func_array | 0.0147 | +0.0008 | +5.84 |
Invoke | 0.0187 | +0.0048 | +34.61 |
ClosureFactory | 0.0207 | +0.0069 | +49.43 |
assignedClosureFactory | 0.0219 | +0.0080 | +57.75 |
directImplementation | 0.0232 | +0.0094 | +67.53 |
InvokeCallUserFunc | 0.0264 | +0.0126 | +90.67 |
以上是 【php】PHP 的 call_user_func_array 方法是否效率很低? 的全部内容, 来源链接: utcz.com/a/103906.html