Last active
November 15, 2019 10:43
-
-
Save slavcodev/0e9a2d89d7fef6b19d8e7801bb81e684 to your computer and use it in GitHub Desktop.
Routers Benchmark
This file contains hidden or 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
<?php | |
declare(strict_types=1); | |
use FastRoute\RouteCollector; | |
use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; | |
use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; | |
use Symfony\Component\Routing\Matcher\UrlMatcher; | |
use Symfony\Component\Routing\RequestContext; | |
use Symfony\Component\Routing\Route; | |
use Symfony\Component\Routing\RouteCollection; | |
use function FastRoute\simpleDispatcher; | |
final class RouterTest extends TestCase | |
{ | |
const STEPS = 10000; | |
protected function setUp(): void | |
{ | |
parent::setUp(); | |
echo "\n> {$this->getName()}\n"; | |
} | |
protected function tearDown(): void | |
{ | |
parent::tearDown(); | |
self::assertTrue(true); | |
} | |
private function createRoutes(): RouteCollection | |
{ | |
$routes = new RouteCollection(); | |
for ($i = 0; $i < 400; ++$i) { | |
$routes->add('yes-static-'.$i, new Route('/abc'.$i)); | |
$routes->add('not-static-'.$i, new Route('/abc{foo}/'.$i)); | |
} | |
return $routes; | |
} | |
/** | |
* @test | |
*/ | |
public function symfony(): void | |
{ | |
$routes = $this->createRoutes(); | |
$matcher = new UrlMatcher($routes, new RequestContext('', 'GET')); | |
// Warm | |
$matcher->match('/abc0'); | |
$matcher->match('/abc0/0'); | |
$matcher->match('/abc399'); | |
$matcher->match('/abc0/399'); | |
$time = microtime(true); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->match('/abc0'); | |
} | |
$this->report('First static', $time, microtime(true)); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->match('/abc399'); | |
} | |
$this->report('Last static', $time, microtime(true)); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->match('/abc0/0'); | |
} | |
$this->report('First dynamic', $time, microtime(true)); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->match('/abc399/399'); | |
} | |
$this->report('Last dynamic', $time, microtime(true)); | |
} | |
/** | |
* @test | |
*/ | |
public function symfonyCompiled(): void | |
{ | |
$routes = $this->createRoutes(); | |
$dumper = new CompiledUrlMatcherDumper($routes); | |
$compiledRoutes = $dumper->getCompiledRoutes(); | |
$matcher = new CompiledUrlMatcher($compiledRoutes, new RequestContext('', 'GET')); | |
// Warm | |
$matcher->match('/abc0'); | |
$matcher->match('/abc0/0'); | |
$matcher->match('/abc399'); | |
$matcher->match('/abc0/399'); | |
$time = microtime(true); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->match('/abc0'); | |
} | |
$this->report('First static', $time, microtime(true)); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->match('/abc399'); | |
} | |
$this->report('Last static', $time, microtime(true)); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->match('/abc0/0'); | |
} | |
$this->report('First dynamic', $time, microtime(true)); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->match('/abc399/399'); | |
} | |
$this->report('Last dynamic', $time, microtime(true)); | |
} | |
/** | |
* @test | |
*/ | |
public function fastroute(): void | |
{ | |
$matcher = simpleDispatcher( | |
static function (RouteCollector $routes): void { | |
for ($i = 0; $i < 400; ++$i) { | |
$routes->addRoute('GET', '/abc' . $i, 'yes-static-'.$i); | |
$routes->addRoute('GET', '/abc{foo}/' . $i, 'not-static-'.$i); | |
} | |
} | |
); | |
// Warm | |
$matcher->dispatch('GET', '/abc0'); | |
$matcher->dispatch('GET', '/abc0/0'); | |
$matcher->dispatch('GET', '/abc399'); | |
$matcher->dispatch('GET', '/abc0/399'); | |
$time = microtime(true); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->dispatch('GET', '/abc0'); | |
} | |
$this->report('First static', $time, microtime(true)); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->dispatch('GET', '/abc399'); | |
} | |
$this->report('Last static', $time, microtime(true)); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->dispatch('GET', '/abc0/0'); | |
} | |
$this->report('First dynamic', $time, microtime(true)); | |
for ($i = 0; $i < self::STEPS; ++$i) { | |
$matcher->dispatch('GET', '/abc399/399'); | |
} | |
$this->report('Last dynamic', $time, microtime(true)); | |
} | |
private function report(string $label, float &$start, float $end): void | |
{ | |
printf("%s: %f ms\n", $label, $end - $start); | |
$start = $end; | |
} | |
} |
Result with xdebug off
> symfony
First static: 0.089548 ms
Last static: 3.154077 ms
First dynamic: 0.097837 ms
Last dynamic: 3.256220 ms
> fastroute
First static: 0.001488 ms
Last static: 0.001487 ms
First dynamic: 0.005097 ms
Last dynamic: 0.121380 ms
Result with compiled routes for Symfony (xdebug off)
> symfony
First static: 0.083611 ms
Last static: 3.227731 ms
First dynamic: 0.092768 ms
Last dynamic: 3.231728 ms
> symfonyCompiled
First static: 0.005310 ms
Last static: 0.005034 ms
First dynamic: 0.011305 ms
Last dynamic: 0.012007 ms
> fastroute
First static: 0.001489 ms
Last static: 0.001482 ms
First dynamic: 0.005152 ms
Last dynamic: 0.113381 ms
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Result