A function call in PHP is expensive. Here is a small benchmark to test it:
<?php const RUNS = 1000000; // 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).
Speaking from personal experience, I write code in a proprietary language that is fairly modern in terms of capability, but function calls are ridiculously expensive, to the point where even typical for loops have to be optimized for speed: for(Integer index = 0, size = someList.
In PHP, a function is declared with the function keyword prefixed with the function name and the calling of a function in a program is done by just calling the name of the function wherever required.
A key benefit of using functions is that they are reusable; if you have a task that needs to be performed a number of times, a function is an ideal solution. They can be either defined by you or by PHP (PHP has a rich collection of built-in functions).
A function call requires that the current execution frame is suspended, and a new frame is created and pushed on the stack. This is relatively expensive, compared to many other operations.
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_END
You can check the implementations of the opcodes in zend_vm_def.h
. Prepend ZEND_
to the names, e.g. for ZEND_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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With