-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature for Timer to measure callable performance #6321
Feature for Timer to measure callable performance #6321
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice PR! I like this new feature, especially the inclusion of callable
which (in my opinion) allows the very valuable array notation benchmarking, not just closures. Our timer()
function is starting to get a bit abstruse, but I'm okay with this expansion unless someone else objects.
Thanks for the contribution @rumpfc! A few notes inline, feel free to discuss.
There are coding style violation. Please fix. |
$this->expectException(RuntimeException::class); | ||
|
||
$timer = new Timer(); | ||
$timer->record('ex', static function () { throw new RuntimeException(); }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a question. If by mistake I made the callable throw an exception, then how can I get the elapsed time since $this->stop($name)
will not be called? Should the invocation of the callable be wrapped in a try-finally
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If an exception is thrown and you don't catch it, then I think you might have other problems than worrying about the time stoppage.
But you also have a point. It does not handle the case of purposely catching exceptions for error handling.
try {
$benchmark->record('test', 'func_that_throws');
} catch (Throwable $e) {
// stop() isn't called yet
}
@kenjis shall we cover this case as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if an exception is thrown after $benchmark->start()
or in $iterator->run()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For $iterator->run()
, nothing is caught internally. It would not record anything in the report and would go out of the method, ignoring all follow up Closures.
For $benchmark->start()
, you would need to call stop()
inside the catch
or finally
block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need try-finally
.
An exception should be thrown in an exceptional case, and not recoverable.
Normally, a developer would modify the code to prevent the exception from occurring.
If a developer really wants to know the elapsed time when an exception is thrown, they can catch and measure it by themselves.
Please fix coding style and failed tests. |
Calling // PHP 7.4 and before
strlen(); // throws ErrorException (extends Exception)
// PHP 8.0 and after
strlen(); // throws ArgumentCountError (extends TypeError) @kenjis I can offer 2 solutions:
|
@rumpfc Not specifically catch Exception in the method. So it's weird to catch only ErrorException. So it's okay to expect Throwable in the test. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Thanks all! |
Description
This is a convinience feature enhancement for
Timer
to measure short code blocks without adding itsstart
/stop
methods before and after the block. The new methodrecord()
accepts a string and a callable as parameters.Which is the equivalent to
It can also return the callables return value
Alternatively the common function
timer()
also accepts an optional callable for the same mechanics. Leaving out the 2nd parameter behaves like before (returning aTimer
instance).Checklist: