【php】PHP 的 call_user_func_array 方法是否效率很低?

Laravel 5.1Facade 类 的 __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 调用

测试结果

【php】PHP 的 call_user_func_array 方法是否效率很低?
我们可以看到,call_user_func_array 所用时间为:1.1608240604401s

测试过程

测试代码如下:

<?php

error_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
InvocationTime (s)Delta (s)%
directFunction0.0089-0.0211-70.19
directStatic0.0098-0.0202-67.39
directLambda0.0109-0.0191-63.52
directInstance0.0116-0.0184-61.31
directClosure0.0150-0.0150-50.15
Invoke0.0282-0.0018-6.13
call_user_func0.0300
ClosureFactory0.0316+0.0016+5.20
assignedClosureFactory0.0328+0.0028+9.28
call_user_func_array0.0399+0.0099+33.02
InvokeCallUserFunc0.0418+0.0118+39.17
directImplementation0.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
InvocationTime (s)Delta (s)%
directFunction0.0043-0.0096-68.92
directStatic0.0050-0.0089-64.04
directInstance0.0058-0.0081-58.22
directLambda0.0063-0.0075-54.44
directClosure0.0081-0.0058-41.57
call_user_func0.0139
call_user_func_array0.0147+0.0008+5.84
Invoke0.0187+0.0048+34.61
ClosureFactory0.0207+0.0069+49.43
assignedClosureFactory0.0219+0.0080+57.75
directImplementation0.0232+0.0094+67.53
InvokeCallUserFunc0.0264+0.0126+90.67

以上是 【php】PHP 的 call_user_func_array 方法是否效率很低? 的全部内容, 来源链接: utcz.com/a/103906.html

回到顶部