From 0db8d7fb6a5396f84f2907e5e595c114982772ff Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 19 Jun 2017 11:42:01 +0200 Subject: [PATCH] Add support for microseconds in Stopwatch --- .../FrameworkExtension.php | 2 +- src/Symfony/Component/Stopwatch/CHANGELOG.md | 2 + src/Symfony/Component/Stopwatch/Section.php | 15 +++-- src/Symfony/Component/Stopwatch/Stopwatch.php | 13 +++- .../Component/Stopwatch/StopwatchEvent.php | 17 +++-- .../Component/Stopwatch/StopwatchPeriod.php | 17 ++--- .../Stopwatch/Tests/StopwatchPeriodTest.php | 67 +++++++++++++++++++ 7 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 src/Symfony/Component/Stopwatch/Tests/StopwatchPeriodTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f3b77f0a12..a3c92a026b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -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'); } diff --git a/src/Symfony/Component/Stopwatch/CHANGELOG.md b/src/Symfony/Component/Stopwatch/CHANGELOG.md index 2a03545ed1..36d0c25f1a 100644 --- a/src/Symfony/Component/Stopwatch/CHANGELOG.md +++ b/src/Symfony/Component/Stopwatch/CHANGELOG.md @@ -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` diff --git a/src/Symfony/Component/Stopwatch/Section.php b/src/Symfony/Component/Stopwatch/Section.php index 2337e03140..d4ff9928f8 100644 --- a/src/Symfony/Component/Stopwatch/Section.php +++ b/src/Symfony/Component/Stopwatch/Section.php @@ -28,6 +28,11 @@ class Section */ private $origin; + /** + * @var bool + */ + private $morePrecision; + /** * @var string */ @@ -41,11 +46,13 @@ 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 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(); diff --git a/src/Symfony/Component/Stopwatch/Stopwatch.php b/src/Symfony/Component/Stopwatch/Stopwatch.php index 562f220f67..cbe08cc7c1 100644 --- a/src/Symfony/Component/Stopwatch/Stopwatch.php +++ b/src/Symfony/Component/Stopwatch/Stopwatch.php @@ -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)); } } diff --git a/src/Symfony/Component/Stopwatch/StopwatchEvent.php b/src/Symfony/Component/Stopwatch/StopwatchEvent.php index 16a30db2aa..0d20f49b13 100644 --- a/src/Symfony/Component/Stopwatch/StopwatchEvent.php +++ b/src/Symfony/Component/Stopwatch/StopwatchEvent.php @@ -33,6 +33,11 @@ class StopwatchEvent */ private $category; + /** + * @var bool + */ + private $morePrecision; + /** * @var float[] */ @@ -41,15 +46,17 @@ class StopwatchEvent /** * Constructor. * - * @param float $origin The origin time in milliseconds - * @param string|null $category The event category or null to use the default + * @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; diff --git a/src/Symfony/Component/Stopwatch/StopwatchPeriod.php b/src/Symfony/Component/Stopwatch/StopwatchPeriod.php index 9876f179aa..c3ae266c9a 100644 --- a/src/Symfony/Component/Stopwatch/StopwatchPeriod.php +++ b/src/Symfony/Component/Stopwatch/StopwatchPeriod.php @@ -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() { diff --git a/src/Symfony/Component/Stopwatch/Tests/StopwatchPeriodTest.php b/src/Symfony/Component/Stopwatch/Tests/StopwatchPeriodTest.php new file mode 100644 index 0000000000..f2387b8285 --- /dev/null +++ b/src/Symfony/Component/Stopwatch/Tests/StopwatchPeriodTest.php @@ -0,0 +1,67 @@ + + * + * 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); + } +}