Measuring execution time is the domain of profilers. In PHP, you could use Xdebug to do so. See Simplest way to profile a PHP script for other suggestions. In any case, a profiler is what you want to use. It's a professional tool for the purpose.
As an alternative, you could invest into an observability tool, like Instana or Tideways. There are others. While observability is somewhat different from profiling, both tools come with code profiling capabilities to complement their observability features. Full disclosure: I work for Instana and am friends with the owner of Tideways.
I am not aware of a good userland no-code approach to adding interceptors to function calls. There are libraries like Componere, runkit or uopz but I don't think you'll get very far with them and you will need to install an extension. If given the choice between installing Xdebug or one of these, I'd go with Xdebug.
A low code approach might be to use attributes as pointed out in the comments to your question. That will still require you to heavily touch up your code because every line of code you want measured needs to have the attribute.
Apart from that, you could hack something together in a namespace:
<?php
namespace My;
foreach (get_defined_functions()['internal'] as $function) {
if ($function === 'assert') continue;
$declaration = sprintf(
'namespace My; function %s() {
$start = \microtime(true);
$retval = \call_user_func_array("%s", \func_get_args());
echo \microtime(true) - $start, PHP_EOL;
return $retval;
}',
$function,
$function,
$function,
$function
);
eval($declaration);
};
echo strtotime('today');
This will output something like
6.9141387939453E-5
1624485600
Demo: https://3v4l.org/r9Rpd
This will create a function for every internal PHP function in the namespace My
, wrapping that internal function. You can insert any code you want to run before and after the function in the function declaration.
PHP will first check the current namespace for a defined function before falling back to looking into the global namespace. Thus, when calling strtotime
, it will invoke My\strtotime
.
There are probably plenty of caveats I didn't think through with this approach. I am not recommending to use that. As I said in the beginning: use a profiler.