rotexsoft / callable-execution-timer
一个简单的PHP库,用于跟踪可调用对象(例如函数/方法)执行所需的总时间(如果需要,它还可以返回可调用对象的执行结果)。
Requires
- php: >=8.1.0
Requires (Dev)
- php-coveralls/php-coveralls: ^2.0
- phpunit/phpunit: ^10.0
- rector/rector: ^1.0.0
- vimeo/psalm: ^5.4
README
一个简单的PHP库,用于跟踪可调用对象(例如函数/方法)执行所花费的总时间(如果需要,它还可以返回执行可调用对象的结果)。
如果您想在应用程序中执行一些简单的执行时间分析,而不使用像debugbar或xdebug这样的完整工具,那么这个包就是您所需要的。
安装
通过composer:(需要PHP 7.4+或PHP 8.0+)。
composer require rotexsoft/callable-execution-timer
分支
以下是此存储库中的分支
- main:包含此包最新主要版本的代码
- 1.x:包含此包的1.x版本代码
简介
一个简单的PHP库,用于跟踪可调用对象(例如函数/方法)执行所花费的总时间以及返回的结果(如果有)。
在此文档的其余部分中,术语可调用对象将主要指函数/方法
此库还提供了与每个执行/调用相关的信息,例如
- 传递给可调用对象的参数(数组)
- 执行可调用对象所需的总时间(以秒为单位,int / float)
- 从调用可调用对象返回的值(mixed)
- 调用可调用对象的文件的绝对路径(字符串)
- 调用可调用对象的文件的精确行号(整数)
执行可调用对象
执行内置PHP函数
让我们调用PHP的内置函数 strtolower 和 strtoupper。
<?php use \FunctionExecutionTimer\CallableExecutionTimer; echo CallableExecutionTimer::callFunc('strtolower', 'strtolower', ['BOO']) . PHP_EOL; // outputs 'boo' echo CallableExecutionTimer::callFunc('strtoupper', 'strtoupper', ['boo']) . PHP_EOL; // outputs 'BOO'
**注意**:传递给 CallableExecutionTimer::callFunc(...) 的第一个参数是要执行的 可调用对象的名字(符合PHP的方法命名约定)。此名称将用于标识与可调用对象执行相关的信息,如本说明文档中稍后所示。
**注意**:传递给 CallableExecutionTimer::callFunc(...) 的第二个参数是要执行的 可调用对象。
**注意**:传递给 CallableExecutionTimer::callFunc(...) 的第三个参数是要传递给要执行的 可调用对象的参数的数组。如果要执行的 可调用对象不接受任何参数,则可以省略此参数。
执行用户定义的函数
<?php use \FunctionExecutionTimer\CallableExecutionTimer; function foobar($arg, $arg2) { return __FUNCTION__ . " got $arg and $arg2"; } // a function that has a by-ref argument function mega(&$a){ $a = 55; return "function mega \$a=$a"; } echo CallableExecutionTimer::callFunc('foobar', 'foobar', ["one", "two"]) . PHP_EOL ; // outputs 'foobar got one and two' $bar = 77; echo CallableExecutionTimer::callFunc('mega', 'mega', [&$bar]) . PHP_EOL ; // outputs 'function mega $a=55' // $bar now has a value of 55 after the execution of the function above
执行类方法
<?php use \FunctionExecutionTimer\CallableExecutionTimer; class foo { function bar($arg, $arg2) { return __METHOD__ . " got $arg and $arg2"; } } class myclass { static function say_hello() { return "Hello!"; } } // execute an instance method echo CallableExecutionTimer::callFunc( 'fooBar', [new foo(), "bar"], ["three", "four"] ) . PHP_EOL ; // outputs 'foo::bar got three and four' // execute a static method $classname = "myclass"; echo CallableExecutionTimer::callFunc( 'myclassSay_hello', [$classname, "say_hello"] ) . PHP_EOL; // outputs 'Hello!' // OR echo CallableExecutionTimer::callFunc( 'myclassSay_hello', $classname ."::say_hello" ) . PHP_EOL; // also outputs 'Hello!'
执行父类和子类方法
<?php use \FunctionExecutionTimer\CallableExecutionTimer; class A { public static function who() { return "A"; } } class B extends A { public static function who() { return "B"; } } // Child calling parent's implementation of method defined in both parent & child echo CallableExecutionTimer::callFunc('B_A_who', [B::class, 'parent::who']) . PHP_EOL; // outputs 'A' // Parent calling its own method echo CallableExecutionTimer::callFunc('A_who', [A::class, 'who']) . PHP_EOL; // outputs 'A' // Child calling its own method echo CallableExecutionTimer::callFunc('B_who', [B::class, 'who']) . PHP_EOL; // outputs 'B'
执行命名空间静态类方法
<?php namespace Foobar { class Foo { static public function test($name) { return "Hello {$name}!"; } } } namespace { //include_once './vendor/autoload.php'; //include your composer autoloader use \FunctionExecutionTimer\CallableExecutionTimer; // Syntax 1 echo CallableExecutionTimer::callFunc( 'FoobarFooTest', "\\Foobar\\Foo::test", ["Hannes"] ) . PHP_EOL; // outputs 'Hello Hannes!' // Syntax 2 echo CallableExecutionTimer::callFunc( 'FoobarFooTest', ["\\Foobar\\Foo", 'test'], ["Philip"] ) . PHP_EOL; // outputs 'Hello Philip!' }
执行lambda / 匿名函数
<?php use \FunctionExecutionTimer\CallableExecutionTimer; $func = function($arg1, $arg2) { return $arg1 * $arg2; }; echo CallableExecutionTimer::callFunc('func', $func, [2, 4]) . PHP_EOL; // outputs 8 echo CallableExecutionTimer::callFunc( 'funcInline', function($arg) { return $arg; }, ['in inline lambda function!'] ) . PHP_EOL; // outputs 'in inline lambda function!' // anonymous function that accepts a by-ref argument $num = 5; echo CallableExecutionTimer::callFunc( 'funcInlineByRef', function(int &$arg) { return "\$arg = " . ++$arg; }, [&$num] ) . PHP_EOL; // outputs '$arg = 6' // $num now has a value of 6 at this point
执行具有 __invoke 方法的类实例的对象
<?php use \FunctionExecutionTimer\CallableExecutionTimer; class C { public function __invoke($name) { return "Hello {$name}"; } } echo CallableExecutionTimer::callFunc('C__invoke', new C(), ['Jane!']) . PHP_EOL; // outputs 'Hello Jane!'
您还可以使用 \FunctionExecutionTimer\CallableExecutionTimer 的实例以如下方式执行可调用对象
<?php use \FunctionExecutionTimer\CallableExecutionTimer; $callableObj1 = new CallableExecutionTimer('strtolowerCallback', 'strtolower'); echo $callableObj1->strtolowerCallback('BOO') . PHP_EOL; // triggers __call & outputs 'boo' // same as $callableObj1->__call('strtolowerCallback', ['BOO']) echo $callableObj1(['BOO']) . PHP_EOL; // triggers __invoke & outputs 'boo' // same as $callableObj1->__invoke(['BOO'])
警告:执行一个具有一个或多个应该通过引用传递的参数的可调用对象时,应使用 \FunctionExecutionTimer\CallableExecutionTimer::callFunc(...) 或通过使用绑定到可调用对象的 \FunctionExecutionTimer\CallableExecutionTimer 实例上的 __invoke(array $args) 机制来执行函数。
通过尝试使用触发 __call() 的方法调用语法在 \FunctionExecutionTimer\CallableExecutionTimer 实例上调用可调用对象是不可行的。
例如,您可以通过以下两种方式执行以下接受引用参数的lambda函数
<?php use \FunctionExecutionTimer\CallableExecutionTimer; $func = function(int &$arg) { return "\$arg = " . ++$arg; }; // Option 1 use CallableExecutionTimer::callFunc(...) $num = -1; echo CallableExecutionTimer::callFunc( 'funcWithRefArg', $func, [&$num] ) . PHP_EOL; // outputs '$arg = 0' & $num will have a value of 0 after this call // Option 2 using the __invoke(array $args) mechanism on the instance of // CallableExecutionTimer the callable is bound to $num = -1; $callableObj2 = new CallableExecutionTimer('funcWithRefArg', $func); echo $callableObj2([&$num]) . PHP_EOL; // triggers the __invoke(array $args) mechanism // which executes the lambda function and // outputs '$arg = 0'. // $num will have a value of 0 after this call /////////////////////////////////////////////////////////////////////////// // NOTE: trying to invoke the function on an instance of // **\FunctionExecutionTimer\CallableExecutionTimer** using the method call // syntax that triggers **__call()** under the hood will not work, $num // will not be passed by reference as expected and you will get a PHP // warning to that effect. // DON'T DO THIS /////////////////////////////////////////////////////////////////////////// $num = -1; $callableObj2 = new CallableExecutionTimer('funcWithRefArg', $func); $numRef = &$num; echo $callableObj2->funcWithRefArg($numRef) . PHP_EOL; // Will throw a PHP Warning. // $numRef will not be passed by // ref because of the way // __call(string $methodName, array $args) // works, meaning that $num will still // have a value of -1 after the call.
检索执行统计信息
有两种方式可以检索通过此库执行的可调用对象执行的每个实例相关的信息
-
您可以通过调用 getLatestBenchmark() 方法来获取您用于执行可调用对象的 \FunctionExecutionTimer\CallableExecutionTimer 实例的信息,以获取通过该对象执行的最新可调用对象执行的信息。此方法返回一个包含以下键(加粗,不包括冒号)的数组
- 函数 : 一个字符串。你标记为可调用的名称(符合PHP的方法命名规范),你执行了该可调用
- args : 一个数组。包含你传递给执行的可调用的参数,如果有,否则将是一个空数组。
- start_time : 一个浮点数或一个整数。可调用执行开始时的纳秒时间戳。
- end_time : 一个浮点数或一个整数。可调用执行结束时的纳秒时间戳。
- total_execution_time_in_seconds : 一个浮点数或一个整数。执行可调用所花费的总秒数。
- return_value : 执行的可调用返回的值,如果有,则为NULL。
- file_called_from : 一个字符串。从该文件执行的绝对路径,其中包含执行的可调用。
- line_called_from : 一个整数。从该文件执行的精确行号。
以下是一个示例
<?php use \FunctionExecutionTimer\CallableExecutionTimer; $funcObj = new CallableExecutionTimer('strtolower', 'strtolower'); echo $funcObj->strtolower('BOO') . PHP_EOL; var_export($funcObj->getLatestBenchmark());
上面的代码将生成如下输出
array ( 'function' => 'strtolower', 'args' => array ( 0 => 'BOO', ), 'start_time' => 81023870126000, 'end_time' => 81023870134000, 'total_execution_time_in_seconds' => 8.0E-6, 'return_value' => 'boo', 'file_called_from' => 'C:\\Code\\callable-execution-timer\\tester.php', 'line_called_from' => 105, )
-
你可以调用 \FunctionExecutionTimer\CallableExecutionTimer::getBenchmarks() 来获取通过
- 所有对 \FunctionExecutionTimer\CallableExecutionTimer::callFunc(...) 的调用执行的所有可调用的信息
- 以及通过 \FunctionExecutionTimer\CallableExecutionTimer 的各种实例执行的所有可调用执行
此方法返回一个数组数组。每个子数组具有上述描述的 getLatestBenchmark() 方法返回的数组的结构。以下是部分示例代码
<?php use \FunctionExecutionTimer\CallableExecutionTimer; // First clear previous benchmark info if any CallableExecutionTimer::clearBenchmarks(); $funcObj = new CallableExecutionTimer('strtolowerMethod', 'strtolower'); echo $funcObj->strtolowerMethod('BOO') . PHP_EOL; echo $funcObj->strtolowerMethod('ABA') . PHP_EOL; echo CallableExecutionTimer::callFunc( 'funcInline', function($arg) { return "Hello $arg !"; }, ['Jane'] ) . PHP_EOL; var_export(CallableExecutionTimer::getBenchmarks());
上面的代码将生成如下输出
array ( 0 => array ( 'function' => 'strtolowerMethod', 'args' => array ( 0 => 'BOO', ), 'start_time' => 87248086831300, 'end_time' => 87248086840600, 'total_execution_time_in_seconds' => 9.3E-6, 'return_value' => 'boo', 'file_called_from' => 'C:\\Code\\callable-execution-timer\\tester.php', 'line_called_from' => 106, ), 1 => array ( 'function' => 'strtolowerMethod', 'args' => array ( 0 => 'ABA', ), 'start_time' => 87248086997700, 'end_time' => 87248087001600, 'total_execution_time_in_seconds' => 3.9E-6, 'return_value' => 'aba', 'file_called_from' => 'C:\\Code\\callable-execution-timer\\tester.php', 'line_called_from' => 108, ), 2 => array ( 'function' => 'funcInline', 'args' => array ( 0 => 'Jane', ), 'start_time' => 87248087019400, 'end_time' => 87248087024100, 'total_execution_time_in_seconds' => 4.7E-6, 'return_value' => 'Hello Jane !', 'file_called_from' => 'C:\\Code\\callable-execution-timer\\tester.php', 'line_called_from' => 110, ), )
建议在开始执行你想要获取执行信息的可调用之前调用 \FunctionExecutionTimer\CallableExecutionTimer::clearBenchmarks()。这将清除先前可调用执行的所有以前执行信息。