• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Benchmarking Ci4 router

#1
Benchmarking Ci 4  router vs Symfony router ..... 35 000 routes most of them static

 results  Ci 4
PHP Code:
Code:
Array
(
    [map_codeigniter] => Array
        (
            [duration] => 0.2808
            [memory] => 48.82 mb
        )

    [match_codeigniter] => Array
        (
            [duration] => 0.4066
            [memory] => 1.06 kb
        )
results Symfony


PHP Code:
Code:
[map_symfony] => Array
        (
          [duration] => 0.078
            [memory] => 26.17 mb
        )

    [symfony_match] => Array
        (
         [duration] => 0.0936
            [memory] => 15.94 mb
        ) 



PHP Code:
Code:
function random_request_url() {
    $characters = 'abcdefghijklmnopqrstuvwxyz';
    $charactersLength = strlen($characters);
    $randomString = '/';
    // create random path of 5-20 characters
    for ($i = 0; $i < rand(5, 20); $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
        if( rand(1, 10) === 1 ) {
           $randomString .= '/';
        }
    }
    // add dynamic route with 10% chance
    if ( rand(1, 10) === 1 ) {
       $randomString = rtrim( $randomString, '/' ) . '/[:part]';
    }
    return $randomString;
}

// generate a random request method
function random_request_method() {
    static $methods = array( 'GET', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE' );
    $random_key = array_rand( $methods );
    return $methods[ $random_key ];



PHP Code:
Code:
$routes = $this->getCollector();
$this->request = Services::request();
    $nRoutes = 35000;
         $requests = array();
         for($i=0; $i<$nRoutes; $i++) {
         $requests[] = array(
        'method' => \random_request_method(),
        'url' => \random_request_url(), 
        'target' => 'App\Controllers\Test::display',
        'name'=>'route_name'.$i
         );
         }    
        $requests[] = array(
        'method' => \random_request_method(),
        'url' => 'blog/hhh', 
        'target' => 'App\Controllers\Test::show',
        'name'=>'routename_bb'
       );
    
    
\Bench::start('map_codeigniter');
   foreach($requests as $r) {
     $routes->add($r['url'], $r['target']);
  }
\Bench::stop('map_codeigniter');
\Bench::start('match_codeigniter');
$router = new Router($routes, $this->request);
        $router->handle('blog/hhh');
        
\Bench::stop('match_codeigniter'); 
PHP Code:
Code:
$nRoutes = 35000;
$requests = array();
for($i=0; $i<$nRoutes; $i++) {
    $requests[] = array(
        'method' => random_request_method(),
        'url' => random_request_url(),
    );
}
echo count($requests);
    Bench::start('symfony');
    $routes = new RouteCollection();
    Bench::start('map_symfony');
 
    foreach($requests as $i=> $r) {
        $route = new Route( $r['url'], array('controller' => 'MyController'));
        $routes->add('handler' . $i, $route);
       
    }
Bench::stop('map_symfony');
$r = $requests[array_rand($requests)];

Bench::start('symfony_match');
    $context = new RequestContext($r['url']);
    $matcher = new UrlMatcher($routes, $context);
     try {
    $parameters = $matcher->match($r['url']);
     } catch (Exception $e) {
        }
        
Bench::stop('symfony_match'); 
Reply

#2
The test is little rigged . Ci4 match last route symfony random route.
But the problem remains . Ci4 router is kinda slow in both :adding routes and matching routes
Reply

#3
(09-12-2019, 01:36 AM)tony.a Wrote: The test is little rigged . Ci4 match last route symfony random route.
But the problem remains . Ci4 router is kinda slow in both :adding routes and matching routes

It's true it hasn't been optimized. But that's how most software works, right? Get it working for the first release, then optimize later. Smile

To be fair - I can't think of many times where you will have an app with 35,000 routes it has to go through so the difference in real world terms is likely a couple of milliseconds. I knew there was potential for boost using techniques like fast-route does, so that might come down the pike in the future (especially if anyone wants to jump in and make it happen sooner).
Support Development  • Practical CodeIgniter 3  • Vulcan - CLI Tools for CI4
Reply

#4
What version of the Symfony router? I know Symfony 4* has pretty much set the benchmark in terms of speed. It's pretty darn fast all around.
Codeigniter is simply one of the tools you need to learn to be a successful developer. Always add more tools to your coding arsenal!
Reply

#5
symfony version 4.3 -4.4 symfony has second higher memory usage  after ci4. 
Symfony not my favorite, request class is also fat eating a lot of memory
France has  36,681 communes, 101 departments, 26 regions.
I have a classified website where city name is the lroute
Altorouter has the best results/sec and lowest memory usage. Same 35 000 routes  for all router tests ,but Altorouter with some optimizations  can match 150 000 routes on a  1.350.000 /second  speed 
Ill put the tests on github
 One option is to use controllers as second  routers and  split the number of routes  , not to match all in front router
Same work in progress with my website ,looking for the best option
 The Ci 4 file cache is the fastest around on par with doctrine cache (but doctrine has advantage of spliting the files across multiple directories ,) phpfastcache the slowest and the fattest
Reply

#6
(09-12-2019, 10:07 AM)tony.a Wrote: symfony version 4.3 -4.4
France has  36,681 communes, 101 departments, 26 regions.
I have a classified website where city name is the lroute
Altorouter has the best results and lowest memory usage. Same 35 000 routes  for all.Altorouter with some optimizations  can match 1.350.000 /second
Ill put the tests on github

Each commune doesn't have its own controller/method does it?

Not sure how your site is structured, but I would handle it with routes something like:

PHP Code:
$routes->get('communes/{id}''CommuneController@details/$1');
$routes->get('departments/{id}''DepartmentController@details/$1');
$routes->get('regions/{id}''RegionController@details/$1'); 

I imagine the URL structure is more involved than that. But even so it would be maybe a dozen routes to handle 1 page per.

If you do actually have 35,000 routes in your files, what benefit do you see from that? Very curious.
Support Development  • Practical CodeIgniter 3  • Vulcan - CLI Tools for CI4
Reply

#7
[quote pid='367285' dateline='1568308620']
Instead of 
[/quote]
communes/{id} 
I wanna have  www.
Mywebsite. Com /paris
Mywebsite/lyon
Mywebsite/paris/for-sale
Mywebsite/paris/for-sale/asc... params  => city controller
 Also mywebsite/for-sale/... params => category controller
Also mywebsite/john-doe /... params => user controller
Reply

#8
PHP Code:
$routes->get('{segment}''RegionController@details/$1'); 
$routes->get('{segment}/for-sale''ForSaleConroller@forRegion/$1'); 
$routes->get('{segment}/{segment}/for-sale''ForSaleConroller@forCommune/$1/$2'); 

Routes like these would allow the format you've listed. You could then use $_GET vars for sorting, search term, etc if needed.

I'm not trying to tell you how to do it, just trying to understand the benefits of having 35,000 routes, and how you would even manage those if they were all hardcoded.
Support Development  • Practical CodeIgniter 3  • Vulcan - CLI Tools for CI4
Reply

#9
At 40 mb and 1 sec  is not an option for sure .
trying not to hit the database to find the first segment and query various tables.
Is a Region ?
Is a city ?
Is a category ?
Is a subcategory ?
Is a page ?
Is a user ?
Altorouter (optimized )  vs Symfony benchmark same 8000 routes  (Spain has 8000 cities ).
Symfony 1 loop  random route match . 1 loop no match
[map_symfony] => Array
        (
            [start] => 1568314486.7859
            [end] => 1568314486.8639
            [start_memory] => 21650600
            [end_memory] => 49116216
            [duration] => 0.07800007
            [memory] => 26.19 mb
        )

    [symfony_match] => Array
        (
            [start] => 1568314486.8639
            [end] => 1568314486.8951
            [start_memory] => 49116592
            [end_memory] => 54674560
            [duration] => 0.03119993
            [memory] => 5.3 mb
        )

    [symfony_no_match] => Array
        (
            [start] => 1568314486.8951
            [end] => 1568314487.1291
            [start_memory] => 54674936
            [end_memory] => 97618904
            [duration] => 0.23399997
            [memory] => 40.95 mb
        )
Altorouter 10000  loops to match 10 000 loops no match 

[map_altorouter] => Array
        (
            [start] => 1568315731.476
            [end] => 1568315731.476
            [start_memory] => 8039096
            [end_memory] => 11265408
            [duration] => 0
            [memory] => 3.08 mb
        )

    [altorouter_match] => Array
        (
            [start] => 1568315731.476
            [end] => 1568315731.5228
            [start_memory] => 11265784
            [end_memory] => 11265784
            [duration] => 0.04680014
            [memory] => NAN b
        )

    [altorouter_no_match] => Array
        (
            [start] => 1568315731.5228
            [end] => 1568315731.5696
            [start_memory] => 11266160
            [end_memory] => 11266160
            [duration] => 0.0467999
            [memory] => NAN b
        )




PHP Code:
$nRoutes 8000;
$requests = array();
for(
$i=0$i<$nRoutes$i++) {
    $requests[] = array(
        'method' => random_request_method(),
        'url' => random_request_url(), 
'target' => 'Home::index',
'name'=>'scriptswatre'.$i
    
);

//echo count($requests);

$router = new AltoRouter();
// map requests
Bench::start('map_altorouter');



foreach(
$requests as $r) {
    $router->map($r['method'], $r['url'], $r['target'],$r['name']);
}
Bench::stop('map_altorouter');

// pick random route to match
$r $requests[array_rand($requests)];
p_print_r($r);
Bench::start('altorouter_match');
for(
$i=0$i<10000$i++) {
  $match $router->match($r['url'], $r['method']);


//p_print_r($match);
Bench::stop('altorouter_match');

Bench::start('altorouter_no_match');
for(
$i=0$i<10000$i++) {
$router->match('/55-foo-bar''GET');
}
Bench::stop('altorouter_no_match');



at extra 3 mb and this speed to match  is a viable option to replace the database lookup
Reply

#10
Ok, that's fair.

I'd probably just cache the page results, personally.

But we are always happy for people to jump in and improve the code, if you're interested.
Support Development  • Practical CodeIgniter 3  • Vulcan - CLI Tools for CI4
Reply


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2019 MyBB Group.