laitimes

PHP runtime performance benchmarks

author:Not bald programmer
PHP runtime performance benchmarks

Test environment

  • Each runtime runs in 1 or 2 Docker containers
  • Each container has 1 CPU and 1GB RAM
  • The load testing tool is located in the same Docker network

Test the application

Symfony provides runtime components. According to the official documentation, it "extracts bootstrap logic from any global state to ensure that the application can run at runtime, as such". This means that you can develop your application using any runtime you like, but run it at peak performance in production. So, not only can we run applications with traditional servers, but we can also use libraries like Swoole, AMPHP, and ReactPHP. Looking ahead, the last two were left out of the competition.

Load testing tools

K6 is used to run load tests. Each runtime runs 3 times, with 10, 100, and 1000 concurrent connections in 30 seconds.

Runtime

  • Apache(prefork模式)+ mod_php
  • Apache(事件模式)+ PHP-FPM
  • Nginx + PHP-FPM
  • Nginx Unit应用服务器
  • Nginx Unit应用服务器
  • Nginx + Roadrunner(fcgi模式)
  • FrankenPHP
  • FrankenPHP (worker mode)
  • Swoole

All runtimes are based on official Docker images. If you don't use an image, copy the application's code into the image during the build process. PHP 8.3 is everywhere except Nginx Unit. At the beginning of 2024, the maximum PHP version supported by Nginx Unit is 8.2.

Unfortunately, I didn't find the latest version of ReactPHP and AMPHP runtimes that are compatible with Symfony 7. PHPPM GitHub and Dockerhub look like they're both abandoned.

Apply the following PHP and Symfony settings:

  • Using php.ini-production (comes with the official Docker container)
  • Opcache is enabled
  • Enable JIT
  • Configure preload based on Symfony best practices
  • Composer自动加载器已优化
  • Symfony runs in production mode
  • The service container is dumped to a single file
  • The Symfony cache warms up during container builds

The application code, as well as the container configuration, can be found on the GitHub https://github.com/DimDev/php-runtimes-benchmark.

outcome

PHP runtime performance benchmarks
PHP runtime performance benchmarks
PHP runtime performance benchmarks
PHP runtime performance benchmarks
PHP runtime performance benchmarks
PHP runtime performance benchmarks
  • 001_Apache+mod_php and 002_Apache+PHP-FPM show almost the same results.
  • 003_Nginx+PHP-FPM is very close to 001_Apache+mod_php and 002_Apache + PHP-FPM at low workloads (concurrent 10 and 100).
  • When the concurrency of 003_Nginx+PHP-FPM is 1000, the number of requests can be served is twice that of the Apache stack
  • 004_Nginx unit. First of all - wow!! It is 3 times faster than the traditional and most popular 003_Nginx+PHP-FPM
  • I don't think there's a big difference between 005_Roadrunner and 006_Nginx+Roadrunner
  • Still, the Roadrunner-based stack is more than 2x faster than 003_Nginx+PHP-FPM
  • 007_FrankenPHP (non-working mode) is very close to 003_Nginx+PHP-FPM from a performance perspective
  • 008_FrankenPHP(worker mode). Double WOW! I don't believe in load testing 3 or 4 times from the first attempt and running. So, when sending 1000 concurrent requests, FrankenPHP (Worker Mode) is 10 times faster than Nginx+PHP-FPM. At the same time, there is also a problem. Unable to use php-ini. production startup container.
  • 009_swoole - Also double WOW!. Almost the same speed as 008_FrankenPHP (wm). Very fast. However, keep in mind that your code should be tuned to run with Swoole. For Symfony, we have a bundle that extends the symfony/runtime component.

Read on