Laravel Facade实现细节考
前两天有人讲Laravel中的Facade的时候,看到了__callStatic
的实现,探究了下为何如此。
现有实现
switch实现
我们在调用Facede的方法的时候,绝大多数都会被__callStatic
来处理,Larvel 5.1的__callStatic
实现如下:
1 | switch (count($args)) { |
这个实现是 Taylor Otwell 最初实现的版本。
cufa实现
是上述switch实现的简化版:
1 | return call_user_func_array([$instance, $method], $args); |
Argument Unpack实现
这个是 Laravel 5.3 的实现。
1 | return $instance->$method(...$args); |
注意,Argument Unpacking 特性在php 5.6才实现。
实现对比
代码如下:
1 | class A |
表中为在各个情况下调用 Facede::get 100000000次的秒数
参数数量 | php70+switch | php70+cufa | php70+unpack | php56+switch | php56+cufa | php56+unpack |
---|---|---|---|---|---|---|
0 | 33 | 39 | 34 | 74 | 107 | 65 |
1 | 38 | 46 | 37 | 84 | 117 | 75 |
2 | 41 | 48 | 38 | 91 | 118 | 80 |
3 | 44 | 52 | 38 | 108 | 125 | 89 |
4 | 50 | 49 | 39 | 118 | 137 | 94 |
5 | 58 | 50 | 41 | 189 | 146 | 99 |
6 | 61 | 53 | 42 | 194 | 155 | 107 |
结论
可以看到,在PHP 5.6下,switch实现比cufa实现,在参数个数比较少的时候,有很大的优势,估计这个也是作者在第一次实现的时候,选择switch实现,而不是代码写起来更简单的cufa的原因吧。
另外,unpack在PHP 5.6下更快,但由于当时需要支持PHP 5.3,所以不能使用。
在Laravel 5.3中,由于最低PHP版本切换到了5.6.4 ,所以可以大胆的使用unpack了。
此外,实际上, PHP 7.0下,unpack在没有参数时,比switch要慢,但是个人觉得差别不大。
最后,PHP 7.0 的速度提升还是很明显的。
参考资料
Laravel Facade实现细节考