feat: FrankenPHP Worker Mode #9889
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This PR adds experimental support for FrankenPHP Worker Mode, allowing to handle multiple HTTP requests within the same PHP process. Instead of bootstrapping the framework for every request (traditional PHP-FPM model), the worker boots once and reuses resources across requests, resulting in 2-3x performance improvements for typical database-driven applications.
How it works
New features
app/Config/WorkerMode.php- Configuration for persistent services and garbage collectionphp spark worker:install- Generates Caddyfile and worker entry pointphp spark worker:uninstall- Removes worker mode filesOptimizations
Database:
BaseConnection::ping()method for connection health checkspg_ping(), other drivers useSELECT 1DatabaseConfig::validateForWorkerMode()- validates connections at request startDatabaseConfig::cleanupForWorkerMode()- detects uncommitted transactions and rolls backSession handlers:
PersistsConnectiontrait for Redis and Memcached handlersServices and state management:
Boot::bootWorker()- one-time initialization for worker modeCodeIgniter::resetForWorkerMode()- resets request-specific stateServices::resetForWorkerMode()- resets non-persistent services between requestsServices::validateForWorkerMode()- validates cache connectionsEvents::cleanupForWorkerMode()- clears event performance dataDebug Toolbar:
Toolbar::reset()- resets collectors between requests (development only)No impact on traditional PHP-FPM
All worker mode methods are only called from the worker entry point (
public/frankenphp-worker.php). When running in traditional PHP-FPM mode viapublic/index.php, none of this code is executed. The changes introduce zero performance overhead for applications not using worker mode.Benchmarks
I also prepared a set of simple benchmarks to evaluate worker mode performance: https://github.com/michalsn/benchmark-codeigniter-frankenphp
Based on existing benchmarks, nginx with PHP-FPM should perform similarly to FrankenPHP running in classic mode. When I attempted to verify this, the results showed roughly 60% of classic mode performance. However, these tests were run in a local development environment that is not properly tuned, which likely skewed the results.
For this reason, I decided not to include the benchmark numbers for nginx with PHP-FPM. In a real-world, properly configured environment, nginx is expected to perform similarly to FrankenPHP in classic mode.
Checklist: