I wanted to quickly take Laravel Octane beta for a spin, as we have been using Swoole for some time and wanted to see how official support performs vs what we have.
Next test is more real world as we now have a web server and database server within a VPC.
Using Laravel Forge
- App server: PHP 8.0.3, AWS t3.small - 2 vCPUs, 2 GB RAM
- Database: AWS RDS MySQL 8.0 db.t3.micro, 2 vCPUs, 1 GB RAM - using private VPC
- SSL certificate
We will use opcache, cache route and config in Laravel, and adjust settings for performance.
We test for 3 min, using 8 threads and 200 connections each.
PHP-FPM Settings
pm = dynamic
pm.max_children = 100
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 40
Nginx - Swoole
upstream swoole-http {
server 127.0.0.1:8000;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name octane.example.com;
server_tokens off;
root /home/forge/octane.example.com/public;
index index.php;
charset utf-8;
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/octane.example.com/server/*;
location = /index.php {
try_files /not_exists @swoole;
}
location / {
try_files $uri $uri/ @swoole;
}
location @swoole {
set $suffix "";
if ($uri = /index.php) {
set $suffix ?$query_string;
}
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header SERVER_PORT $server_port;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://swoole-http$suffix;
}
}
wrk -t8 -c200 -d3m https://testdomain.com/api/ping
wrk -t8 -c200 -d3m https://testdomain.com/api/users
wrk -t8 -c200 -d3m https://testdomain.com/api/users/1
Route | Nginx to PHP-FPM on AWS t3.small, RDS db.t3.micro | Nginx to Octane Swoole on AWS t3.small, RDS db.t3.micro |
---|---|---|
/api/ping | 295 req/sec, 98% App CPU | 832 req/sec, 84% App CPU |
/api/users | 77 req/sec, 85% App CPU, 88% DB CPU, 90 DB conn | 113 req/sec, 29% App CPU, 54% DB CPU, 4 DB conn |
/api/users/:id | 189 req/sec, 91% App CPU, 10% DB CPU, 16 DB conn | 453 req/sec, 61% App CPU, 6% DB CPU, 2 DB conn |
- Macbook Pro 2019
- Laravel 8.35.1
- Laravel Octane 0.1.0 beta
- Laravel Sail
- Wrk
Basic Laravel app with 5000 users seeded into the database. Only installed Sail and Octane packages. Otherwise 100% vanilla setup.
Route::get('/users', function () {
return response()->json(User::query()->paginate());
});
Route::get('/users/{userId}', function (int $userId) {
return response()->json(User::query()->findOrFail($userId));
});
Route::get('/ping', function() {
return response()->json(['message' => 'pong']);
});
Route | Response | MySQL |
---|---|---|
/api/ping | Returns a string | No |
/api/users | Returns a paginated list of users | Yes |
/api/users/:id | Returns a user | Yes |
wrk -t4 -c50 -d30s http://localhost/api/ping
wrk -t4 -c50 -d30s http://localhost/api/users
wrk -t4 -c50 -d30s http://localhost/api/users/1
All the tests have been conducted on my MacBook Pro 2019 using Docker. Im sure using native would yield better performance. However, we care about the difference - not so much about the actaul numbers.
- Nginx to PHP-FPM: classic nginx to fpm setup using docker
- Nginx proxy to Swoole. Using Laravel-swoole package and nginx
- Laravel Octane beta and Sail
Route | Nginx to PHP-FPM | Nginx to Swoole | Octane Swoole HTTP |
---|---|---|---|
/api/ping | 131 req/sec | 369 req/sec | 766 req/sec |
/api/users | 82 req/sec | 152 req/sec | 201 req/sec |
/api/users/:id | 104 req/sec | 290 req/sec | 545 req/sec |
All the tests have been conducted on my MacBook using Docker. Im sure using native would yield much better performance. However, we care about the difference - not so much about the actaul numbers.
Again, very quick tests - but for now it looks promising.
And about memory usage ?