为什么PHP函数调用*如此昂贵? [英] Why are PHP function calls *so* expensive?
问题描述
PHP中的函数调用非常昂贵。这是测试它的一个小基准:
//创建测试字符串
$ string = str_repeat('a',1000);
$ maxChars = 500;
//带函数调用
$ start = microtime(true); ($ i = 0; $ i< RUNS; ++ $ i){
strlen($ string)< = $ maxChars;
;
echo'with function call:',microtime(true) - $ start,\\\
;
//不带函数调用
$ start = microtime(true); ($ i = 0; $ i< RUNS; ++ $ i){
!isset($ string [$ maxChars]);
。
}
echo'without function call:',microtime(true) - $ start;
这首先使用函数测试功能相同的代码( strlen
),然后不使用函数( isset
不是函数)。
输出如下:
带函数调用:4.5108239650726
不带函数调用:0.84017300605774
$ b正如你所看到的,使用函数调用的实现比不调用任何函数的实现慢5倍以上(5.38)倍。 p>
我想知道为什么函数调用非常昂贵。主要瓶颈是什么?它是哈希表中的查找吗?或者是什么这么慢?
我重新讨论了这个问题,并决定再次运行基准测试,XDebug完全禁用不只是分析禁用)。这表明,我的测试相当复杂,这次我得到了10000000次运行:
带函数调用:3.152988910675
没有函数调用:1.4107749462128
这里函数调用的速度大约是缓慢的两倍(2.23)所以差异就小得多了。
我刚刚在PHP 5.4.0快照上测试了上面的代码,以下结果:
函数调用:2.3795559406281
无函数调用:0.90840601921082
这里差距再次略微增大(2.62)。 (但是,这两种方法的执行时间相差很大)。
解决方案PHP中的函数调用非常昂贵,注意,
isset
不是一个函数(它有一个特殊的操作码) ,所以速度更快。
对于这样一个简单的程序:
<?php
func(arg1,arg2);
有六个(每个参数四个+一个)操作码:
1 INIT_FCALL_BY_NAME'func','func'
2 EXT_FCALL_BEGIN
3 SEND_VAL'arg1'
4 SEND_VAL'arg2'
5 DO_FCALL_BY_NAME 2
6 EXT_FCALL_END
您可以在
zend_vm_def.h
。在名称前加上ZEND _
,例如对于ZEND_INIT_FCALL_BY_NAME
和搜索。
ZEND_DO_FCALL_BY_NAME
特别复杂。然后是函数本身的实现,它必须展开堆栈,检查类型,转换zvals并可能将它们分离并实际工作...A function call in PHP is expensive. Here is a small benchmark to test it:
// create test string $string = str_repeat('a', 1000); $maxChars = 500; // with function call $start = microtime(true); for ($i = 0; $i < RUNS; ++$i) { strlen($string) <= $maxChars; } echo 'with function call: ', microtime(true) - $start, "\n"; // without function call $start = microtime(true); for ($i = 0; $i < RUNS; ++$i) { !isset($string[$maxChars]); } echo 'without function call: ', microtime(true) - $start;
This tests a functionally identical code using a function first (
strlen
) and then without using a function (isset
isn't a function).I get the following output:
with function call: 4.5108239650726 without function call: 0.84017300605774
As you can see the implementation using a function call is more than five (5.38) times slower than the implementation not calling any function.
I would like to know why a function call is so expensive. What's the main bottleneck? Is it the lookup in the hash table? Or what is so slow?
I revisited this question, and decided to run the benchmark again, with XDebug completely disabled (not just profiling disabled). This showed, that my tests were fairly convoluted, this time, with 10000000 runs I got:
with function call: 3.152988910675 without function call: 1.4107749462128
Here a function call only is approximately twice (2.23) as slow, so the difference is by far smaller.
I just tested the above code on a PHP 5.4.0 snapshot and got the following results:
with function call: 2.3795559406281 without function call: 0.90840601921082
Here the difference got slightly bigger again (2.62). (But on the over hand the execution time of both methods dropped quite significantly).
解决方案Function calls are expensive in PHP because there's lot of stuff being done.
Note that
isset
is not a function (it has a special opcode for it), so it's faster.For a simple program like this:
<?php func("arg1", "arg2");
There are six (four + one for each argument) opcodes:
1 INIT_FCALL_BY_NAME 'func', 'func' 2 EXT_FCALL_BEGIN 3 SEND_VAL 'arg1' 4 SEND_VAL 'arg2' 5 DO_FCALL_BY_NAME 2 6 EXT_FCALL_ENDYou can check the implementations of the opcodes in
zend_vm_def.h
. PrependZEND_
to the names, e.g. forZEND_INIT_FCALL_BY_NAME
and search.
ZEND_DO_FCALL_BY_NAME
is particularly complicated. Then there's the the implementation of the function itself, which must unwind the stack, check the types, convert the zvals and possibly separate them and to the actual work...这篇关于为什么PHP函数调用*如此昂贵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!