-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Add support for microseconds in Stopwatch #23223
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
Conversation
$this->memory = memory_get_usage(true); | ||
} | ||
|
||
/** | ||
* Gets the relative time of the start of the period. | ||
* | ||
* @return int The time (in milliseconds) | ||
* @return float The time (in milliseconds) | ||
*/ | ||
public function getStartTime() |
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.
changing output of this is BC breaker, and for one that like to write in new php in strict mode, it will crash his software.
<?php
declare(strict_types=1);
function NON_STRICTLY_TYPEHINTED_SYMFONY_METHOD___getStartTime_org() { return 123; }
function NON_STRICTLY_TYPEHINTED_SYMFONY_METHOD___getStartTime_new() { return 123.456; }
function USER_FUNCTION_THAT_CONSUMES_SYMFONY_OUTPUT(int $a) {
echo $a;
}
USER_FUNCTION_THAT_CONSUMES_SYMFONY_OUTPUT(NON_STRICTLY_TYPEHINTED_SYMFONY_METHOD___getStartTime_org()); // OK
USER_FUNCTION_THAT_CONSUMES_SYMFONY_OUTPUT(NON_STRICTLY_TYPEHINTED_SYMFONY_METHOD___getStartTime_new()); // Fatal error: Uncaught TypeError: Argument 1 passed to USER_FUNCTION_THAT_CONSUMES_SYMFONY_OUTPUT() must be of the type integer, float given
while i do really like the idea, it's bc breaker, as proven |
@keradus it's a BC break ... that's why I submitted to 3.4 branch ... should I submit it instead to 4.0? |
3.4 is for features, not bc breakers, isn't it ? |
vs
|
We cannot break BC in 4.0 without a migration path from 3.4. So target master would not change anything. What we need to do instead is to add an argument to those methods to get the value as a float and return a casted int if not. |
that's why I requested future-compat layer :) |
$this->start = (int) $start; | ||
$this->end = (int) $end; | ||
$this->start = $start; | ||
$this->end = $end; |
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.
Next to the previous mentioned BC break in the issue, no type cast will also be error prone.
I've made some changes. Please tell me if I'm going in the right direction. Thanks! |
*/ | ||
public function __construct($start, $end) | ||
public function __construct($start, $end /*, $useMicroPrecision = false*/) |
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.
No need to keep this commented, as it's still optional since you're adding a default value. So it won't break BC. (However you could add the bool
typehint commented for 4.0)
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.
Indeed, especially for a constructor method.
LGTM but as is, it does not really help as the profiling still won't get the more precise time, right? |
Not sure if this is what was asked for in #18756 ... but the screenshots in the PR are real: now we see details for < 0ms events. |
How does it work? Where are you passing |
} | ||
|
||
$this->start = $morePrecision ? $start : (int) $start; | ||
$this->end = $morePrecision ? $end : (int) $end; |
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.
do we care about detecting invalid inputs, eg arrays ?
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.
no
@fabpot I understand your comment now. I had forgotten to commit the change that enables more precision 😊 |
@@ -177,7 +177,7 @@ public function getDuration() | |||
|
|||
for ($i = 0; $i < $left; ++$i) { | |||
$index = $stopped + $i; | |||
$periods[] = new StopwatchPeriod($this->started[$index], $this->getNow()); | |||
$periods[] = new StopwatchPeriod($this->started[$index], $this->getNow(), true); |
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.
This also makes the StopwatchEvent::getStartTime()
, ::getEndTime()
and ::getDuration()
return int|float
, right?
So I fear it won't be enough to ensure BC :/ You'll need to be able to configure the $morePrecision
flag higher.
Or, wouldn't it be possible to simply add the flag to the three methods mentioned above, to either return an int (default) or a float (more precision): public function getStartTime(/*bool $morePrecision = false*/)
instead (and always store floats in the private StopwatchPeriod
properties)?
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.
adding param to method is BC breaker.
you are thinking more about StopWatchPreciseEvent
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.
Indeed, except if the new arg is commented until 4.0, and implementations not having it trigger deprecations. StopWatchPreciseEvent
could be a solution, but you still need a simple way to say you want to use it, higher in the Stopwatch API, without affecting existing code, as it may impact other consumers.
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 I get you right - if whole param would be commented, then the way to retrieve it would be to func_get_args
.
Big 👎 from my side to that practices.
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.
We already use this "practice" for BC reasons in quite a lot of places in Symfony core.
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.
@keradus See all func_get_arg
instances in Symfony. This practice is actually pretty novel in terms of providing new APIs without causing BC breaks.
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.
And those only are the remaining ones in the master branch.
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.
@keradus Using func_get_args/func_num_args()
is the only way to have proper upgrade paths when adding an argument to a method.
They can make the code less readable for a period, but that's for making it better at the end, that is what BC layers are all about.
See e.g.
https://github.com/symfony/symfony/blob/3.3/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php#L61
https://github.com/symfony/symfony/blob/3.3/src/Symfony/Component/HttpFoundation/Request.php#L597
https://github.com/symfony/symfony/blob/3.3/src/Symfony/Component/DependencyInjection/Definition.php#L805
Worst: https://github.com/symfony/symfony/blob/af4703f6f209a9abc387f81b98e00fad46b89a38/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php#L25..#L106
All of these have been removed from master already, and I guess we're all happy about what the changes involving those layers will provide.
*/ | ||
public function __construct($start, $end) | ||
public function __construct($start, $end, /* bool */ $morePrecision = false) |
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.
bool here is no longer needed
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'm skeptical about this practice of adding commented type hints, especially when it just duplicates the docblock
$this->start = (int) $start; | ||
$this->end = (int) $end; | ||
$this->start = $morePrecision ? $start : (int) $start; | ||
$this->end = $morePrecision ? $end : (int) $end; |
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.
missing cast to float IMHO
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.
with minor comments
Approval dismissed, sorry :) IF we happen to really want to have the "BC" flag, then the implementation is partial: we cannot have these hardcoded |
and that's the bc breaker, and I show how it breaks my code. please do respect SEMVER or officially say project is no longer following it. |
@keradus The "BC break" is limited to use of |
not, it's not only limited to Changing return type in 4.0 is fine, as 4.0 is not yet released and 4.0 is dedicated place for BC breakers. http://symfony.com/doc/current/contributing/code/bc.html
|
|
@robfrawley assertion could be on the argument of one of your methods, and you could be using the output of the component as input for your code. |
@robfrawley , exactly as @stof said |
I've updated this PR to follow @ogizanagi's comments. |
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.
The collectors should be updated to use the new flag when using getters.
@@ -5,3 +5,5 @@ CHANGELOG | |||
----- | |||
|
|||
* added the `Stopwatch::reset()` method | |||
* allowed to measure sub-millisecond times by introducing a third argument to |
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.
The changelog entry needs to be updated too :)
@@ -97,7 +97,7 @@ public function stop() | |||
throw new \LogicException('stop() called but start() has not been called before.'); | |||
} | |||
|
|||
$this->periods[] = new StopwatchPeriod(array_pop($this->started), $this->getNow()); | |||
$this->periods[] = new StopwatchPeriod(array_pop($this->started), $this->getNow(), true); |
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.
The third argument is not used anymore (same below)
*/ | ||
public function __construct($start, $end) | ||
{ | ||
$this->start = (int) $start; | ||
$this->end = (int) $end; | ||
$this->start = $start; |
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.
Shouldn't it be casted to float here to avoid issues with strict types ? (otherwise getters might return an int even with the $morePrecision
flag to true
)
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.
yep. and currently, passing eg strings will cause odd working of method, while previously they would be converted in constructor already
After discussing it with @nicolas-grekas, we're proposing a different implementation for this feature. |
The issue I see with this new implementation over the flag in getters is that you'll probably update the |
Thank you @javiereguiluz. |
This PR was squashed before being merged into the 3.4 branch (closes #23223). Discussion ---------- Add support for microseconds in Stopwatch | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | yes | BC breaks? | no? | Deprecations? | no | Tests pass? | yes | Fixed tickets | #18756 | License | MIT | Doc PR | - Stopwatch component already supports microseconds (and nanoseconds, etc.) ... but the problem is that it converts the millisecond times to integers, so anything smaller to 1 millisecond is lost. This PR changes that to fix issues like the one explained in #18756. ### Before  ### After  Commits ------- 0db8d7f Add support for microseconds in Stopwatch
Great to see this without BC breakers ;) |
…h (javiereguiluz) This PR was squashed before being merged into the 3.4 branch (closes #8146). Discussion ---------- Added a tip about the support of microseconds in Stopwatch This documents symfony/symfony#23223. See also https://symfony.com/blog/new-in-symfony-3-4-stopwatch-improvements. Commits ------- 24718a6 Added a tip about the support of microseconds in Stopwatch
Stopwatch component already supports microseconds (and nanoseconds, etc.) ... but the problem is that it converts the millisecond times to integers, so anything smaller to 1 millisecond is lost. This PR changes that to fix issues like the one explained in #18756.
Before
After