feature #23223 Add support for microseconds in Stopwatch (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
![before-stopwatch](https://user-images.githubusercontent.com/73419/27279393-c745db54-54e4-11e7-8f26-01e2063604ce.png)
### After
![after-stopwatch](https://user-images.githubusercontent.com/73419/27279396-c8894dac-54e4-11e7-9a3a-bff027377047.png)
Commits
-------
0db8d7fb6a
Add support for microseconds in Stopwatch
This commit is contained in:
commit
82036a388b
@ -652,7 +652,7 @@ class FrameworkExtension extends Extension
|
||||
$loader->load('debug_prod.xml');
|
||||
|
||||
if (class_exists(Stopwatch::class)) {
|
||||
$container->register('debug.stopwatch', Stopwatch::class);
|
||||
$container->register('debug.stopwatch', Stopwatch::class)->addArgument(true);
|
||||
$container->setAlias(Stopwatch::class, 'debug.stopwatch');
|
||||
}
|
||||
|
||||
|
@ -5,3 +5,5 @@ CHANGELOG
|
||||
-----
|
||||
|
||||
* added the `Stopwatch::reset()` method
|
||||
* allowed to measure sub-millisecond times by introducing an argument to the
|
||||
constructor of `Stopwatch`
|
||||
|
@ -28,6 +28,11 @@ class Section
|
||||
*/
|
||||
private $origin;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $morePrecision;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@ -42,10 +47,12 @@ class Section
|
||||
* Constructor.
|
||||
*
|
||||
* @param float|null $origin Set the origin of the events in this section, use null to set their origin to their start time
|
||||
* @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision
|
||||
*/
|
||||
public function __construct($origin = null)
|
||||
public function __construct($origin = null, $morePrecision = false)
|
||||
{
|
||||
$this->origin = is_numeric($origin) ? $origin : null;
|
||||
$this->morePrecision = $morePrecision;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,7 +81,7 @@ class Section
|
||||
public function open($id)
|
||||
{
|
||||
if (null === $session = $this->get($id)) {
|
||||
$session = $this->children[] = new self(microtime(true) * 1000);
|
||||
$session = $this->children[] = new self(microtime(true) * 1000, $this->morePrecision);
|
||||
}
|
||||
|
||||
return $session;
|
||||
@ -113,7 +120,7 @@ class Section
|
||||
public function startEvent($name, $category)
|
||||
{
|
||||
if (!isset($this->events[$name])) {
|
||||
$this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category);
|
||||
$this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category, $this->morePrecision);
|
||||
}
|
||||
|
||||
return $this->events[$name]->start();
|
||||
|
@ -18,6 +18,11 @@ namespace Symfony\Component\Stopwatch;
|
||||
*/
|
||||
class Stopwatch
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $morePrecision;
|
||||
|
||||
/**
|
||||
* @var Section[]
|
||||
*/
|
||||
@ -28,9 +33,13 @@ class Stopwatch
|
||||
*/
|
||||
private $activeSections;
|
||||
|
||||
public function __construct()
|
||||
/**
|
||||
* @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision
|
||||
*/
|
||||
public function __construct($morePrecision = false)
|
||||
{
|
||||
$this->reset();
|
||||
$this->morePrecision = $morePrecision;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,6 +171,6 @@ class Stopwatch
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->sections = $this->activeSections = array('__root__' => new Section('__root__'));
|
||||
$this->sections = $this->activeSections = array('__root__' => new Section('__root__', $this->morePrecision));
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,11 @@ class StopwatchEvent
|
||||
*/
|
||||
private $category;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $morePrecision;
|
||||
|
||||
/**
|
||||
* @var float[]
|
||||
*/
|
||||
@ -43,13 +48,15 @@ class StopwatchEvent
|
||||
*
|
||||
* @param float $origin The origin time in milliseconds
|
||||
* @param string|null $category The event category or null to use the default
|
||||
* @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision
|
||||
*
|
||||
* @throws \InvalidArgumentException When the raw time is not valid
|
||||
*/
|
||||
public function __construct($origin, $category = null)
|
||||
public function __construct($origin, $category = null, $morePrecision = false)
|
||||
{
|
||||
$this->origin = $this->formatTime($origin);
|
||||
$this->category = is_string($category) ? $category : 'default';
|
||||
$this->morePrecision = $morePrecision;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +104,7 @@ class StopwatchEvent
|
||||
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(), $this->morePrecision);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -177,7 +184,7 @@ class StopwatchEvent
|
||||
|
||||
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(), $this->morePrecision);
|
||||
}
|
||||
|
||||
$total = 0;
|
||||
|
@ -25,20 +25,21 @@ class StopwatchPeriod
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $start The relative time of the start of the period (in milliseconds)
|
||||
* @param int $end The relative time of the end of the period (in milliseconds)
|
||||
* @param int|float $start The relative time of the start of the period (in milliseconds)
|
||||
* @param int|float $end The relative time of the end of the period (in milliseconds)
|
||||
* @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision
|
||||
*/
|
||||
public function __construct($start, $end)
|
||||
public function __construct($start, $end, $morePrecision = false)
|
||||
{
|
||||
$this->start = (int) $start;
|
||||
$this->end = (int) $end;
|
||||
$this->start = $morePrecision ? (float) $start : (int) $start;
|
||||
$this->end = $morePrecision ? (float) $end : (int) $end;
|
||||
$this->memory = memory_get_usage(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relative time of the start of the period.
|
||||
*
|
||||
* @return int The time (in milliseconds)
|
||||
* @return int|float The time (in milliseconds)
|
||||
*/
|
||||
public function getStartTime()
|
||||
{
|
||||
@ -48,7 +49,7 @@ class StopwatchPeriod
|
||||
/**
|
||||
* Gets the relative time of the end of the period.
|
||||
*
|
||||
* @return int The time (in milliseconds)
|
||||
* @return int|float The time (in milliseconds)
|
||||
*/
|
||||
public function getEndTime()
|
||||
{
|
||||
@ -58,7 +59,7 @@ class StopwatchPeriod
|
||||
/**
|
||||
* Gets the time spent in this period.
|
||||
*
|
||||
* @return int The period duration (in milliseconds)
|
||||
* @return int|float The period duration (in milliseconds)
|
||||
*/
|
||||
public function getDuration()
|
||||
{
|
||||
|
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Stopwatch\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Stopwatch\StopwatchPeriod;
|
||||
|
||||
class StopwatchPeriodTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideTimeValues
|
||||
*/
|
||||
public function testGetStartTime($start, $useMorePrecision, $expected)
|
||||
{
|
||||
$period = new StopwatchPeriod($start, $start, $useMorePrecision);
|
||||
$this->assertSame($expected, $period->getStartTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideTimeValues
|
||||
*/
|
||||
public function testGetEndTime($end, $useMorePrecision, $expected)
|
||||
{
|
||||
$period = new StopwatchPeriod($end, $end, $useMorePrecision);
|
||||
$this->assertSame($expected, $period->getEndTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideDurationValues
|
||||
*/
|
||||
public function testGetDuration($start, $end, $useMorePrecision, $duration)
|
||||
{
|
||||
$period = new StopwatchPeriod($start, $end, $useMorePrecision);
|
||||
$this->assertSame($duration, $period->getDuration());
|
||||
}
|
||||
|
||||
public function provideTimeValues()
|
||||
{
|
||||
yield array(0, false, 0);
|
||||
yield array(0, true, 0.0);
|
||||
yield array(0.0, false, 0);
|
||||
yield array(0.0, true, 0.0);
|
||||
yield array(2.71, false, 2);
|
||||
yield array(2.71, true, 2.71);
|
||||
}
|
||||
|
||||
public function provideDurationValues()
|
||||
{
|
||||
yield array(0, 0, false, 0);
|
||||
yield array(0, 0, true, 0.0);
|
||||
yield array(0.0, 0.0, false, 0);
|
||||
yield array(0.0, 0.0, true, 0.0);
|
||||
yield array(2, 3.14, false, 1);
|
||||
yield array(2, 3.14, true, 1.14);
|
||||
yield array(2.71, 3.14, false, 1);
|
||||
yield array(2.71, 3.14, true, 0.43);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user