Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve performance, add internal
Clock
, reuse clock in same tick
- Loading branch information
Showing
7 changed files
with
254 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?php | ||
|
||
namespace React\Http\Io; | ||
|
||
use React\EventLoop\LoopInterface; | ||
|
||
/** | ||
* [internal] Clock source that returns current timestamp and memoize clock for same tick | ||
* | ||
* This is mostly used as an internal optimization to avoid unneeded syscalls to | ||
* get the current system time multiple times within the same loop tick. For the | ||
* purpose of the HTTP server, the clock is assumed to not change to a | ||
* significant degree within the same loop tick. If you need a high precision | ||
* clock source, you may want to use `\hrtime()` instead (PHP 7.3+). | ||
* | ||
* The API is modelled to resemble the PSR-20 `ClockInterface` (in draft at the | ||
* time of writing this), but uses a `float` return value for performance | ||
* reasons instead. | ||
* | ||
* Note that this is an internal class only and nothing you should usually care | ||
* about for outside use. | ||
* | ||
* @internal | ||
*/ | ||
class Clock | ||
{ | ||
/** @var LoopInterface $loop */ | ||
private $loop; | ||
|
||
/** @var ?float */ | ||
private $now; | ||
|
||
public function __construct(LoopInterface $loop) | ||
{ | ||
$this->loop = $loop; | ||
} | ||
|
||
/** @return float */ | ||
public function now() | ||
{ | ||
if ($this->now === null) { | ||
$this->now = \microtime(true); | ||
|
||
// remember clock for current loop tick only and update on next tick | ||
$now =& $this->now; | ||
$this->loop->futureTick(function () use (&$now) { | ||
assert($now !== null); | ||
$now = null; | ||
}); | ||
} | ||
|
||
return $this->now; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
|
||
namespace React\Tests\Http\Io; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use React\Http\Io\Clock; | ||
|
||
class ClockTest extends TestCase | ||
{ | ||
public function testNowReturnsSameTimestampMultipleTimesInSameTick() | ||
{ | ||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); | ||
|
||
$clock = new Clock($loop); | ||
|
||
$now = $clock->now(); | ||
$this->assertIsFloat($now); | ||
$this->assertEquals($now, $clock->now()); | ||
} | ||
|
||
public function testNowResetsMemoizedTimestampOnFutureTick() | ||
{ | ||
$tick = null; | ||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); | ||
$loop->expects($this->once())->method('futureTick')->with($this->callback(function (&$ref) use (&$tick) { | ||
$tick = $ref; | ||
return true; | ||
})); | ||
|
||
$clock = new Clock($loop); | ||
|
||
$now = $clock->now(); | ||
|
||
$ref = new \ReflectionProperty($clock, 'now'); | ||
$ref->setAccessible(true); | ||
$this->assertEquals($now, $ref->getValue($clock)); | ||
|
||
$this->assertNotNull($tick); | ||
$tick(); | ||
|
||
$this->assertNull($ref->getValue($clock)); | ||
} | ||
} |
Oops, something went wrong.