If you followed the WordPress Install Guide you are leaving performance on the table for your website. The WordPress Install Guide defaults to Apache’s mod PHP which is definitely leaving performance on the table.
Here is how to fix that in Ubuntu 20.04:
- install php-fpm:
sudo apt install php-fpm
- disable mod_php and mpm_prefork:
sudo a2dismod php mpm_prefork
- enable mpm_event proxy_fcgi and setenvif:
sudo a2enmod mpm_event proxy_fcgi setenvif
- enable the php-fpm configuration file:
sudo a2enconf php7.4-fpm
- mark apache2 as a manually installed package:
sudo apt-mark manual apache2
- remove mod_php:
sudo apt purge libapache2-mod-php*
That takes care of the general Apache configuration. The next configuration adjustments need to be done at the vhost level. Substitute the correct information for YOUREMAIL, YOURDOMAIN, and WPDIR, and you are good to go.
<VirtualHost *:443>
Protocols h2 http/1.1
ServerName YOURDOMAIN
ServerAdmin YOUREMAIL@YOURDOMAIN.COM
DocumentRoot "WPDIR"
<Directory "WPDIR">
<FilesMatch "\.php$">
#Proxy php files to php-fpm
SetHandler "proxy:unix:/run/php/php-fpm.sock|fcgi://localhost/"
</FilesMatch>
Options All
AllowOverride All
DirectoryIndex index.php
Require all granted
</Directory>
#Protect the uploads directory.
<Directory "WPDIR/wp-content/uploads/">
<FilesMatch "\.php$">
SetHandler none
Require all denied
</FilesMatch>
</Directory>
#snip extraneous stuff
</VirtualHost>
Let me take a minute to talk about performance. I have a small Atom 230 based ITX computer that I use for some network administration tasks and as a CPU limited system for benchmarking.
robert@pallas:~$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Address sizes: 32 bits physical, 48 bits virtual
CPU(s): 2
On-line CPU(s) list: 0,1
Thread(s) per core: 2
Core(s) per socket: 1
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 28
Model name: Intel(R) Atom(TM) CPU 230 @ 1.60GHz
Stepping: 2
CPU MHz: 1595.763
BogoMIPS: 3191.77
L1d cache: 24 KiB
L1i cache: 32 KiB
L2 cache: 512 KiB
NUMA node0 CPU(s): 0,1
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Spec store bypass: Not affected
Vulnerability Spectre v1: Not affected
Vulnerability Spectre v2: Not affected
Vulnerability Srbds: Not affected
Vulnerability Tsx async abort: Not affected
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 ss h
t tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts nopl cpuid aperfmperf pni dtes64 monitor ds_cpl
tm2 ssse3 cx16 xtpr pdcm movbe lahf_lm dtherm
robert@pallas:~$
Pallas isn’t fast but it does make a good test bench for what performance difference you might see on a very limited server. I will leave the full benchmark tests below. To summarize the performance looks pretty similar from a users perspective. However, if I point out that the mpm_prefork test had a load average of 88.72 while the mpm_event test had a load average of 11.04 you can see that while mpm_event may not be faster than mp_prefork from a users perspective it does help with server load.
You can expect a return to this topic once I find a way to stress test HTTP 2 connections.
Prefork
robert@Venus:~$ sudo ab -c 100 -n 100000 -r http://192.168.1.12/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.12 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software: Apache/2.4.41
Server Hostname: 192.168.1.12
Server Port: 80
Document Path: /
Document Length: 10918 bytes
Concurrency Level: 100
Time taken for tests: 110.875 seconds
Complete requests: 100000
Failed requests: 0
Total transferred: 1119200000 bytes
HTML transferred: 1091800000 bytes
Requests per second: 901.91 [#/sec] (mean)
Time per request: 110.875 [ms] (mean)
Time per request: 1.109 [ms] (mean, across all concurrent requests)
Transfer rate: 9857.63 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 4 14.6 3 1039
Processing: 2 107 77.7 108 611
Waiting: 1 29 27.3 21 403
Total: 3 111 78.9 112 1260
Percentage of the requests served within a certain time (ms)
50% 112
66% 151
75% 170
80% 182
90% 212
95% 239
98% 273
99% 298
100% 1260 (longest request)
robert@Venus:~$
Event
robert@Venus:~$ sudo ab -c 100 -n 100000 -r http://192.168.1.12/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.12 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software: Apache/2.4.41
Server Hostname: 192.168.1.12
Server Port: 80
Document Path: /
Document Length: 10918 bytes
Concurrency Level: 100
Time taken for tests: 118.068 seconds
Complete requests: 100000
Failed requests: 0
Total transferred: 1119200000 bytes
HTML transferred: 1091800000 bytes
Requests per second: 846.97 [#/sec] (mean)
Time per request: 118.068 [ms] (mean)
Time per request: 1.181 [ms] (mean, across all concurrent requests)
Transfer rate: 9257.12 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 40.6 1 3143
Processing: 11 115 25.5 110 454
Waiting: 2 108 21.4 107 384
Total: 19 118 47.7 111 3235
Percentage of the requests served within a certain time (ms)
50% 111
66% 115
75% 121
80% 128
90% 147
95% 165
98% 192
99% 216
100% 3235 (longest request)
robert@Venus:~$
—Robert