php7 calluserfuncarray,【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 调用

测试结果

0ad893f33994f74d8d1037a29639291a.png

我们可以看到,call_user_func_array 所用时间为:1.1608240604401s

测试过程

测试代码如下:

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值