Skip to content

Instantly share code, notes, and snippets.

@kevindees
Last active July 2, 2018 18:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevindees/7b50a384b8110edfb7f09ef99a910c70 to your computer and use it in GitHub Desktop.
Save kevindees/7b50a384b8110edfb7f09ef99a910c70 to your computer and use it in GitHub Desktop.
<?php
list($script, $uri, $n) = $argv;
$s = microtime(true);
function dispatch($uri, $routes) {
$path = explode('/', trim($uri, '/'));
$c = count($path);
foreach ($routes as $i => $route) {
// $r = explode('/', $route[0][0]); almost no diff event with explode on / if not using an array
$r = $route[0];
if($c == count($r)) {
$args = [];
foreach ($r as $k => $part) {
if($part != $path[$k] && $part[0] != ':') {break;}
if($part[0] == ':') {$args[substr($part, 1)] = $path[$k];}
if ($k == $c - 1) {return [$route, $args];}
}
}
}
return null;
}
$routes = [
[['bar',':id'], function() {}],
[['last',':id'], function() {}],
[['foo',':id',':name'], function() {}],
[['end',':id'], function() {}],
[['end',':id',':name'], function() {}],
];
$range = range(1, $n ?? 1);
foreach ($range as $i) {
$result = dispatch($uri ?? '/end/23', $routes);
// var_dump($result);
}
echo ( microtime(true) - $s) * 1000;
<?php
list($script, $uri, $n) = $argv;
$s = microtime(true);
function dispatch($uri, $routes) {
$regex = ['#^(?'];
foreach ($routes as $i => $route) {
$regex[] = $route[0] . '(*MARK:'.$i.')';
}
$regex = implode('|', $regex) . ')$#x';
preg_match($regex, $uri, $m);
$r = $routes[$m['MARK']];
$args = [];
foreach ($r[1] as $i => $arg) {
$args[$arg] = $m[$i + 1];
}
return [$r, $args];
}
$routes = [
['bar\/(\d+)',['id'], function() {}],
['last\/(\d+)',['id'], function() {}],
['foo\/(\d+)\/(.+)', ['id', 'name'], function() {}],
['end\/(\d+)',['id'], function() {}],
['end\/(\d+)\/(.+)',['id', 'name'], function() {}],
];
$range = range(1, $n ?? 1);
foreach ($range as $i) {
$result = dispatch($uri ?? '/last/23', $routes);
}
echo ( microtime(true) - $s) * 1000;
@kevindees
Copy link
Author

kevindees commented Jul 2, 2018

A not-so-scientific router speed test. I've tried to distill these routers to the bare minimum needed to return the route, mapped args and a controller.

Run Commands:

// args: uri, "num times to run"
php regex-router.php bar/23 1
php count-router.php bar/23 1

Large Set ~200 routes

Regex: 0.304ms
Count: 0.118ms

Small Set ~5 routes

Regex: 0.086ms
Count: 0.056ms

I'm testing the regex method vs. my count version. However, I'm not grouping the regex version. Regardless, these implementations do not seem to break down even with more massive sets if routes and both are high-speed. I would like to think a complied router using the regex method would significantly outpace the count version.

However, the Regex version has the apparent benefits of complex pattern matching.

  1. https://medium.com/@nicolas.grekas/making-symfonys-router-77-7x-faster-1-2-958e3754f0e1
  2. http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html

My conclusion is that there are better places to optimize a system. Having one less file inclusion or class would likely make up the difference in speed. Also, use a tested router against your specific application and domain. The best performance will come from knowing your options and then implementing a router that best fits your application.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment