Routing performance in Micro app

Dear valued community and fellow developers!

I am in the process of creating a fairly simple REST API and at the moment this project has about 212 routes. When doing some basic profiling I noticed that even for actions with complex database queries more than 30% percent of the total execution time for a request is lost even before the correct handler is found and executed.

Some data from the profiling: webgrind call graph webgrind cost data

So as I will get well over 1000 routes - which really is not that much as every GET also is accompanied by an OPTIONS and a HEAD action - I am concerned about performance already.

As it is clear that it is wasted time to completly reinitialize the routing for every new request I tried to cache the (Micro) app object with the help of ACPU but this fails because the object contains some unserializable closures...

I am really looking forward for some advice, thank you for your efforts in advance!

edited Sep '17

Post your example route here (i.e. Router configuration). You're not using Micro Collection for your routes? Also, I see you're using Windows OS, have you tried to run tests on GNU/Linux?

And you're not the first one to report performance hit with Phalcon's Router component, I guess that needs to be coded in a better way for that many routes.

Have you considered something like ReactPHP to jump in as a remedy, as Phalcon is "Request/Response framework" too.

http://marcjschmidt.de/blog/2014/02/08/php-high-performance.html

https://gnugat.github.io/2016/04/13/super-speed-sf-react-php.html



4.7k

If you have a small number of frequently used routes, you can put them at the bottom of the table so they are processed first. That helped in one of my tests.

I also added some code to load only relevant routes. As an example, if the first part of the request is /admin/, only the admin routes are added.

Maybe you are using controlles as handlers and not using lazy?



252
edited Sep '17

>Maybe you are using controlles as handlers and not using lazy?

I am quite sure that lazy loading is used, the code for all handlers looks like the following:

    $pathCollection ->setPrefix('/v1/einsatz')
            ->setHandler('\BritApi\Controllers\EinsatzController')
            ->setLazy(true);

    $pathCollection->options('/', 'optionsBase');
    $pathCollection->get('/', 'get');
    // $pathCollection->head('/', 'get');
    $pathCollection->post('/', 'post');
...
    $app = new \Phalcon\Mvc\Micro($di);
    foreach ($collections as $collection)   $app->mount($collection);

    $app->handle();


252
edited Sep '17

>I also added some code to load only relevant routes. As an example, if the first part of the request is /admin/, only the admin routes are added.

Thank you, as prefix matching is not implemented in Phalcon at the moment I implemented this just as you suggested. Now, only collections which prefix matches the request URL are mounted.

However, I still think that it would be most efficient if it would be possible to cache the routes or event the whole app object with something like APCU or similar.

It's no point, there will be wasted time for serialize and unserialize. I was testing it, i have around 300-400 routes in my app, no difference between creating each time router and caching it. With caching it was slower even.



252

>It's no point, there will be wasted time for serialize and unserialize. I was testing it, i have around 300-400 routes in my app, no difference between creating each time router and caching it. With caching it was slower even.

Thank you for testing this and letting us know. However, I think you agree that there is some optimization potential in route handling.

edited Sep '17

Yes but not caching stuff. Actually adding routes itself is really fastest part of router.