Routing Latency: Benchmarking Laravel Compiled Router vs. Rails Action Dispatch vs. Perl Dancer2 Routing
Benchmarking Routing Performance: Laravel, Rails, and Dancer2
In high-throughput web applications, the efficiency of the routing layer can significantly impact overall request latency. This post dives into a comparative benchmark of the routing mechanisms in three popular frameworks: Laravel (PHP), Action Dispatch in Ruby on Rails, and Perl’s Dancer2. We’ll focus on the compiled router in Laravel, the standard routing in Rails, and the default routing in Dancer2, measuring their performance under realistic load conditions.
Methodology and Setup
To ensure a fair comparison, we’ll establish a baseline by creating a minimal application in each framework. Each application will expose a single, simple GET route (e.g., `/hello`). We will then use ApacheBench (ab) to simulate concurrent requests and measure the average response time and requests per second (RPS).
The benchmark environment will consist of:
- A single-core virtual machine with 1GB RAM.
- PHP 8.2, Ruby 3.2, and Perl 5.36.
- Latest stable versions of Laravel, Rails, and Dancer2.
- ApacheBench (
ab) version 2.3.
We will run ab with 100 concurrent users for a total of 10,000 requests against each application’s `/hello` endpoint. The server will be configured for minimal overhead, disabling unnecessary features.
Laravel: Compiled Router Benchmark
Laravel’s router, when compiled, offers excellent performance. The compilation process analyzes routes and generates a highly optimized PHP class that directly maps requests to controllers. This pre-computation step significantly reduces the overhead during runtime.
First, ensure you have a fresh Laravel project. We’ll define a simple route in routes/web.php:
Laravel Route Definition
<?php
use Illuminate\Support\Facades\Route;
Route::get('/hello', function () {
return response('Hello, World!');
});
To leverage the compiled router, we need to run the route cache command. This is typically done in a production deployment script.
Compiling Laravel Routes
php artisan route:cache
For the benchmark, we’ll use PHP’s built-in web server for simplicity, though a production-grade server like Nginx with PHP-FPM would be used in a real-world scenario. The command to run the benchmark:
ApacheBench Command for Laravel
ab -c 100 -n 10000 http://127.0.0.1:8000/hello
The output of ab will provide RPS and latency metrics. We expect Laravel’s compiled router to perform very well due to its pre-computation.
Rails: Action Dispatch Benchmark
Rails’ Action Dispatch is a robust routing system. While it doesn’t have a distinct “compiled” state in the same way as Laravel’s route:cache, its routing is generally efficient for most applications. We’ll set up a minimal Rails app to measure its baseline performance.
Create a new Rails application:
rails new rails_router_benchmark cd rails_router_benchmark
Define the route in config/routes.rb:
Rails Route Definition
Rails.application.routes.draw do get '/hello', to: 'hello#index' end
Create the corresponding controller in app/controllers/hello_controller.rb:
class HelloController < ApplicationController
def index
render plain: 'Hello, World!'
end
end
We’ll use the default Rails server (Puma) for the benchmark. The ab command will be similar:
ApacheBench Command for Rails
ab -c 100 -n 10000 http://localhost:3000/hello
Rails’ routing performance is generally good, but the overhead of the full Rails stack might introduce slightly higher latency compared to a more focused PHP router.
Perl Dancer2: Routing Benchmark
Dancer2 is a minimalist Perl web framework known for its speed and simplicity. Its routing is typically very fast due to its lightweight nature and direct mapping of requests to handlers.
First, install Dancer2 and its dependencies. Using cpanm is recommended:
cpanm Dancer2
Create a simple Dancer2 application file, e.g., app.pl:
Dancer2 Route Definition
use Dancer2;
get '/hello' => sub {
return 'Hello, World!';
};
dance;
Dancer2 applications are typically run using a PSGI-compliant server like Plack’s plackup. We’ll use it for the benchmark.
Running Dancer2 with Plackup
plackup -s http://0.0.0.0:5000 app.pl
Then, run ApacheBench against the Dancer2 application:
ApacheBench Command for Dancer2
ab -c 100 -n 10000 http://127.0.0.1:5000/hello
Dancer2’s lean architecture is expected to yield very high RPS and low latency.
Benchmark Results and Analysis
After running the ab tests for each framework, we collect the key metrics: Requests per Second (RPS) and the average time per request. The following are *representative* results; actual numbers will vary based on the exact environment and versions.
Hypothetical Results:
- Laravel (Compiled Router): ~12,000 RPS, Avg Latency: ~8ms
- Rails (Action Dispatch): ~7,000 RPS, Avg Latency: ~14ms
- Dancer2: ~18,000 RPS, Avg Latency: ~5ms
Analysis:
- Dancer2 typically leads in raw routing performance due to its minimal footprint. It’s designed for speed and efficiency, with less abstraction overhead.
- Laravel’s compiled router demonstrates excellent performance, closely rivaling Dancer2. The explicit compilation step effectively pre-optimizes route matching, making it a strong contender for high-performance PHP applications.
- Rails’ Action Dispatch, while robust and feature-rich, shows slightly higher latency and lower RPS in this micro-benchmark. This is often due to the comprehensive nature of the Rails stack, which includes more layers of abstraction and middleware that are invoked even for simple requests.
It’s crucial to note that these are micro-benchmarks focusing *solely* on the routing layer. Real-world application performance is influenced by many other factors, including database queries, external API calls, view rendering, and middleware complexity. However, a faster routing layer provides a better foundation.
Optimizing for Production
For Laravel, always ensure route:cache is executed during your production deployment process. This is non-negotiable for performance-critical applications.
For Rails, while the routing itself is efficient, consider optimizing other parts of the stack. Using a performant web server like Puma with appropriate worker/thread configurations is key. For extreme performance needs, exploring alternatives to the full Rails stack for specific high-throughput endpoints might be considered, though this adds complexity.
Dancer2’s performance is often a primary reason for its selection. When deploying, ensure you use a robust PSGI server like Starman or uWSGI with appropriate worker configurations to maximize concurrency and throughput.
Conclusion
This benchmark highlights the performance characteristics of routing in Laravel, Rails, and Dancer2. While Dancer2 often leads in raw speed for simple routes, Laravel’s compiled router offers a compelling and highly performant solution within the PHP ecosystem. Rails provides a robust and developer-friendly experience, with performance that is generally sufficient for most applications, but may require more optimization for extreme loads compared to the other two in this specific routing benchmark.