mod_php vs php-fpm Performance Benchmark [Surprising Results]
Have you ever wondered if Apache mod-php
is faster than php-fpm
with Nginx? I surely did.
Each time this question arises, I do a quick research, and I cannot seem to find a definitive answer. It seems that the recommended way to run PHP websites nowadays is to use php-fpm
with Nginx, but is that the best method? Some articles state that php-fpm
is 300% faster than mod-php
, other articles state that mod-php
is faster, and so on.
This is why I've decided to conduct my own tests and performance benchmark and settle this debate once and for all.
The result surprised me.
The test environment
- Machine: Hetzner VPS with 2 dedicated AMD CPUs, 8GB RAM, 80GB SSD
- Benchmark machine: separate VPS (in the same region)
- Benchmark tool: bombardier (golang)
- OS: Ubuntu 22.04
- PHP version: PHP 8.2.9
- mod-php web server: Apache/2.4.52 with mod-php 8.2.9
- php-fpm web server: nginx/1.18.0 with php-fpm 8.2.9
- php.ini custom config:
// php.ini // default config opcache.memory_consumption=256 opcache.max_accelerated_files=20000 opcache.validate_timestamps=0 realpath_cache_size=4096K realpath_cache_ttl=600
This is the suggested PHP configuration for maximum performance for Symfony production environments.
Both servers use the same php.ini file!
Apache mpm prefork module configuration
# /etc/apache2/mods-available/mpm_prefork.conf
StartServers 5
MinSpareServers 50
MaxSpareServers 100
MaxRequestWorkers 150
MaxConnectionsPerChild 0
I've deliberately chosen a high value for MinSpareServers
because more spare servers mean fewer cold starts and better performance in general.
Nginx process manager configuration
; /etc/php/8.2/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 500
The test app
I chose Symfony PHP framework for the test app, and I've created a simple app with one page that renders some text. No database queries because they can distort the results.
Benchmark setup
The exact command to run the tests is
bombardier -c 200 -d 1m -l http://IP_HERE/
which translates to
- Concurrent requests: 200
- Duration: 1 minute
The results
Let's see how both methods compare in each category.
Average requests per second
In the average requests per second, the race is neck to neck with Nginx php-fpm
having a slight advantage.
Average latency
In the average latency, Nginx with php-fpm again has a slight advantage over Apache mod php.
Max latency
In the max latency category, things get a little bit more interesting.
It seems that Apache mod-php has a maximum latency of 10 seconds. I'll repeat - 10 seconds where Nginx php-fpm has a max latency of only 320.16ms.
Ten seconds of latency for a simple page is terrible and concerning.
Nginx php-fpm here is a clear winner by a lot.
Timeouts
Apache mod-php had 205 timeouts, whereas Nginx php-fpm had ZERO.
Again, Nginx php-fpm is the clear winner here.
Also, having that many timeouts is a bit concerning. That tells me the Apache limit was reached.
Nginx php-fpm latency distribution
Nginx php-fpm shows stable latency distribution, which is a good thing! This means the performance is solid without fluctuations.
Apache mod-php latency distribution
I can't tell the same about Apache mod-php.
The latency distribution has a lot of fractionations. Again, this shows the Apache limit was reached.
Raw results
root@ubuntu-test-bench:~# bombardier -c 200 -d 1m -l http://phpfpm/
Bombarding http://phpfpm:80/ for 1m0s using 200 connection(s)
[===========================================] 1m0s
Done!
Statistics Avg Stdev Max
Reqs/sec 781.55 57.29 993.02
Latency 255.43ms 9.08ms 320.16ms
Latency Distribution
50% 255.28ms
75% 257.38ms
90% 259.49ms
95% 261.25ms
99% 269.54ms
HTTP codes:
1xx - 0, 2xx - 47070, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 0.90MB/s
root@ubuntu-test-bench:~# bombardier -c 200 -d 1m -l http://modphp/
Bombarding http://modphp:80/ for 1m0s using 200 connection(s)
[===========================================] 1m0s
Done!
Statistics Avg Stdev Max
Reqs/sec 690.88 130.38 3421.26
Latency 289.55ms 0.86s 10.03s
Latency Distribution
50% 200.18ms
75% 270.75ms
90% 358.24ms
95% 401.93ms
99% 1.83s
HTTP codes:
1xx - 0, 2xx - 41425, 3xx - 0, 4xx - 0, 5xx - 0
others - 205
Errors:
timeout - 205
Throughput: 790.21KB/s
Conclusion
The performance tests and benchmarks have provided valuable insights into the comparison between Nginx with PHP-FPM and Apache with mod_php. The results point toward Nginx PHP-FPM as the clear winner in terms of performance and stability.
Nginx PHP-FPM stands out with better metrics such as higher average requests per second and lower average latency. It also excels in avoiding prolonged delays, as evidenced by its lead in maximum latency over Apache mod_php.
Additionally, Nginx PHP-FPM is more reliable under pressure, as it doesn't experience timeouts like Apache mod_php, which had 205 timeouts. Nginx PHP-FPM's stable latency distribution further demonstrates its consistent performance, while Apache mod_php appears to struggle.
In summary, developers looking for both performance and reliability are encouraged to choose Nginx with PHP-FPM. These findings provide valuable guidance for optimizing web server configurations to enhance user experiences and improve application performance.