Last active
November 15, 2019 10:43
-
-
Save slavcodev/0e9a2d89d7fef6b19d8e7801bb81e684 to your computer and use it in GitHub Desktop.
Routers Benchmark
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
<?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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Result with compiled routes for Symfony (xdebug off)