Perfect! I ran some tests today with tweaking various numbers and looked at recommendations online too. It's mostly a copy of yours @imc67 in the end but with a lower MaxConnectionsPerChild. Ran a bunch of different tests with different numbers but concluded that was the best bang for the buck so-to-speak given the 4 GB memory max set on each WP app.
It's a mix of default values from the Ubuntu install and the default Apache values in the original package too (for the 256 MaxRequestWorkers for example). I'm pleased with the results.
Here's what I have for reference now, and I used ab (Apache Benchmark) to run some performance tests and had significant improvements over the defaults. Thought I'd share the testing results in case anyone was interested.
New mpm_prefork.conf I'm using:
# Restart the app if you make changes to this file
<IfModule mpm_prefork_module>
# On startup, start these many servers
StartServers 5
# At any given time, keep atleast these many servers
MinSpareServers 5
# At any given time, keep atmost these many idle servers (this is always >= MinSpareServers+1)
MaxSpareServers 10
# Maximum number of servers at any given instant. Requests will be queued after this
MaxRequestWorkers 256
# Recycle process after handling these many requests. This protected against accidental memory leaks
MaxConnectionsPerChild 500
</IfModule>
Resources:
https://httpd.apache.org/docs/2.4/mod/prefork.html
https://exampleconfig.com/view/apache-ubuntu20-04-etc-apache2-mods-available-mpm_prefork-conf
https://www.woktron.com/secure/knowledgebase/133/How-to-optimize-Apache-performance.html
https://www.maketecheasier.com/optimizing-apache-part-1/
Results from ab with default settings that come with Cloudron's WP package: (note the rather large spread between min and max request times)
Concurrency Level: 50
Time taken for tests: 12.391 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 84813000 bytes
HTML transferred: 84205000 bytes
Requests per second: 80.70 [#/sec] (mean)
Time per request: 619.574 [ms] (mean)
Time per request: 12.391 [ms] (mean, across all concurrent requests)
Transfer rate: 6684.04 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 227 291 36.4 287 401
Processing: 220 281 122.2 252 1039
Waiting: 144 190 120.0 161 954
Total: 451 572 127.3 546 1285
Percentage of the requests served within a certain time (ms)
50% 546
66% 570
75% 584
80% 594
90% 624
95% 818
98% 1091
99% 1261
100% 1285 (longest request)
Results after tweaking to the above new configuration: (note that the max request time here is about 60% faster still than original config results and overall a much more consistent behaviour too!)
Concurrency Level: 50
Time taken for tests: 11.358 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 84813000 bytes
HTML transferred: 84205000 bytes
Requests per second: 88.04 [#/sec] (mean)
Time per request: 567.899 [ms] (mean)
Time per request: 11.358 [ms] (mean, across all concurrent requests)
Transfer rate: 7292.24 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 230 287 26.9 283 389
Processing: 220 252 17.3 249 329
Waiting: 144 160 10.0 157 217
Total: 467 539 33.0 538 649
Percentage of the requests served within a certain time (ms)
50% 538
66% 550
75% 559
80% 567
90% 584
95% 599
98% 618
99% 622
100% 649 (longest request)