DEV Community

Cover image for Teeny, a route system for PHP

Teeny, a route system for PHP

Guilherme Nascimento on February 03, 2021

Teeny is a micro-route system that is really micro, supports PHP 5.3 to PHP 8, is extremely simple and ready to use. For create your project use: ...
Collapse
 
hbgl profile image
hbgl

I am a little disappointed that you used the naive implementation of sequentially matching regular expressions for routes with parameters.

Collapse
 
brcontainer profile image
Guilherme Nascimento

I am very grateful for your feedback. Any suggestions are welcome, if you have an idea to improve this I am willing to implement it.

Collapse
 
hbgl profile image
hbgl • Edited

Sure. Not too long ago, I was looking into route matching solutions for PHP and found nikic/FastRoute. The basic idea behind FastRoute is that you do not match a path against each pattern one by one, but instead you combine all patterns and match in one shot. By bundling the patterns, you provide more information to the regex engine, which, in theory, can lead to better performance.

Then the question becomes, how do combine the patterns? In FastRoute, a path is matched against chunks of patterns with 10 to 30 patterns per chunk. It is a good solution, but it is ultimately a workaround for the limitations of the underlying PCRE engine. This blog post explains the implementation in greater detail.

So next, I was looking for a regex engine with first class support for testing against multiple patterns. I found Hyperscan which is a "high-performance multiple regex matching library" developed by Intel. It is a C++ library with a C API, so one could write a PHP extension that exposes PHP bindings for Hyperscan.

You could of course implement your own solution with a radix tree or another algorithm instead of using a regex engine.

Thread Thread
 
haruanm profile image
Haruan Justino

I understand the suggestion, seems to be interesting, at the same time, how much performance it would improve?
I feel that this solution would make the debugging complex and wouldn't meaningfully improve the performance.

Thread Thread
 
brcontainer profile image
Guilherme Nascimento • Edited

Thanks for comment! Apparently you are correct, at least in the initial tests I did, using ApacheBench. Perhaps the complexity of taking advantage of a configuration was more costly than a simple sequential implementation. Tested with Apache2.4 + PHP7.4 + 16GB RAM + Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz + M.2 (SSD):

FastRoute:

  • ab -n 1000 -c 10 http://localhost/fastroute/articles/12345/foobar results: Requests per second: 1473.39
  • Memory usage (peak after register shutdown): 0.487Mb
<?php
require 'vendor/autoload.php';

$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
    $r->addRoute('GET', '/fastroute/users', 'hello_world');
    $r->addRoute('GET', '/fastroute/user/{id:\d+}', 'hello_world');
    $r->addRoute('GET', '/fastroute/articles', 'hello_world');
    $r->addRoute('GET', '/fastroute/articles/{id:\d+}/{title}', 'hello_world');
});
Enter fullscreen mode Exit fullscreen mode

Teeny:

  • ab -n 1000 -c 10 http://localhost/teeny/articles/12345/foobar results: Requests per second: 2506.86
  • Memory usage (peak after register shutdown): 0.388Mb
<?php
require_once 'vendor/teeny.php';
require_once 'vendor/autoload.php';

$app = new \Inphinit\Teeny;

$app->action('GET', '/users', 'hello_world');
$app->action('GET', '/user/{id:num}', 'hello_world');
$app->action('GET', '/articles', 'hello_world');
$app->action('GET', '/articles/<id:num>/<title>', 'hello_world');
Enter fullscreen mode Exit fullscreen mode

More requests per second is better.

Thread Thread
 
hbgl profile image
hbgl

The performance impact depends heavily on your application. If you only have a couple of routes, then it probably doesn't matter which router you use. I did some testing with around 300 routes. The difference between a sequentially scanning router like Symfony Routing and an batch scanning router like FastRoute is noticeable.

Here is the setup that I used for benchmarking: github.com/hbgl/php-routing-bench

Collapse
 
sroehrl profile image
neoan

Really nice! Or should I say cute, given the size?