Closed Macek007 closed 1 week ago
What session driver / database driver are you using? How many CPU cores does your server have? Are you setting APP_ENV=production
? Are you logging something?
50
requests per second feels kinda low to be honest,
on my 20 Core i9 laptop in WSL I can get ~8.000
requests per second with a single Laravel Eloquent query, local mysql and cookie session driver.
It's still interesting though that you are seeing such a difference for big queries. I wonder what the bottleneck here could be, since at that point you're mainly benchmarking your database and PHP/eloquent. I'll try and see if I can reproduce this.
So I managed to reproduce your benchmarks and they reveal something interesting. Not necessarily about FrankenPHP, but more about MySQL (which is the bottleneck here). When reading 1000 Eloquent models per request, if I limit FrankenPHP to just 3 workers (3 CPU cores), it will handle the same amount or even more requests, which indicates that MySQL is at its limits. Paradoxically, MySQL will then be able to handle more requests if the requesting server is slower, aka if there are less connections.
When using the mysql:8.0
Docker image I see a similar slowdown to what you are getting, but when using the postgres
Docker I'm actually able to handle 10x more requests.
This is kinda surprising since I expected MySQL to only be slower on writes, not on reads. But apparently PostgresSQL outperforms MySQL on big reads significantly? (or the mysql
Docker image is just unoptimized).
I can give you the full breakdown + comparisons + recommendations if you share the Docker image you are using (I'm not sure how to fully set up Apache with Laravel).
What happened?
I’ve been experimenting with Laravel Octane + FrankenPHP. Initially, the benchmarks were quite promising, but after real-world usage, I discovered a few bottlenecks. Here’s my experience.
I have two very similar Dockerfiles: one is based on the php:8.3.13-apache-bookworm image, and the other on dunglas/frankenphp:php8.13.3-bookworm. Both use the same
php.ini
configuration. The FrankenPHP container is started with:I ran benchmarks on an API for an ERP system that involves numerous database queries, some of which return large datasets.
Response on Cached Requests
The first test was on requests that use cache (using spatie/laravel-responsecache). All tests were conducted with the command:
The results were similar when testing in the browser.
PHP:
FrankenPHP:
The results were excellent, showing around a 150% improvement with FrankenPHP.
Response on Requests Returning Simple Data
For this test, I used requests that return simple data, such as enums or lookup tables. Typically, these involve only a single query.
PHP:
FrankenPHP:
Again, the results were impressive, with FrankenPHP showing about a 122% improvement.
Requests with Large Datasets
Next, I tested requests that return a dataset of 1,000 rows using Eloquent models with 15+ relations. I confirmed there were no N+1 query issues, and the database queries themselves took around a few hundred milliseconds (up to 500ms). However, the remaining time was spent in PHP runtime. After some xdebug tracing, I found that a significant amount of time was spent on model hydration.
PHP:
FrankenPHP:
In this scenario, FrankenPHP was about 20% slower.
I’ve spent many hours trying to eliminate various factors without much success. I tried adjusting
php.ini
settings, aggressive OPCache and JIT conf, testing on both a local machine (MacBook + Docker) and a server environment (Ryzen + Debian + Kubernetes).Does anyone have any ideas? Has anyone experienced something similar?
Build Type
Docker (Debian Bookworm)
Worker Mode
Yes
Operating System
GNU/Linux
CPU Architecture
x86_64
PHP configuration
Relevant log output
No response