Add support for microseconds in Stopwatch

This commit is contained in:
Javier Eguiluz 2017-06-19 11:42:01 +02:00 committed by Fabien Potencier
parent 0d06bbc3d3
commit 0db8d7fb6a
7 changed files with 113 additions and 20 deletions

View File

@ -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');
}

View File

@ -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`

View File

@ -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();

View File

@ -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));
}
}

View File

@ -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;

View File

@ -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()
{

View File

@ -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);
}
}