MaxClients and MaxRequestsPerChild on MPM Prefork

Hey guys,

Finally getting my head into proper Apache performance tuning and these forums are proving invaluable.

I've currently got a Linode 512 running Apache MPM Prefork, PHP, Mysql and a send only exim mailer. No fancy apache mods either. I've got a WordPress site which I'm testing performance with.

A couple of quick q's.

1.) I've found with the WordPress Quick Cache plugin I can get away with the following apache conf

 <ifmodule mpm_prefork_module="">StartServers          2
    MinSpareServers       2
    MaxSpareServers      5
    MaxClients          30
    ServerLimit         30
    MaxRequestsPerChild   4000</ifmodule> 

Keepalives are also off.

I've been benchmarking the WordPress site and reviewing modstatus and top via ssh while ab is running (1000 requests, 200 concurrent). I can see via modstatus that apache is handling 30 requests at a go.

e.g. via mod_status webpage:

30 requests currently being processed, 0 idle workers.

Does this mean with prefork your MaxClients setting is in effect your max concurrent inbound connection requests? If not, why does mod status always consistently show apache is serving 30 requests at a time?

I would have thought that each child process could handle multiple requests up to the value set in MaxRequestsperChild no?

2.) Before I go off testing nginx, anyone got any good benchmarks for what kind of req/sec I can get from a Linode 512 with (MPM Prefork, mod_php, mysql,exim) and with WordPress running with any of the leading caching plugins. I'm currently getting the following kind of numbers for ab -n 1000 -c 200:

Concurrency Level:      200
Time taken for tests:   60.260 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      120079720 bytes
HTML transferred:       119663890 bytes
Requests per second:    16.59 [#/sec] (mean)
Time per request:       12051.985 [ms] (mean)
Time per request:       60.260 [ms] (mean, across all concurrent requests)
Transfer rate:          1945.99 [Kbytes/sec] received

I think I should be able to sweat it more. The WP setup is a test install running no additional plugins but has a couple of hundred dummy pages and dummy posts.

12 Replies

The MaxClients directive sets the limit on the number of simultaneous requests that will be served. Any connection attempts over the MaxClients limit will normally be queued, up to a number based on the ListenBacklog directive. Once a child process is freed at the end of a different request, the connection will then be serviced.

The MaxRequestsPerChild directive sets the limit on the number of requests that an individual child server process will handle. After MaxRequestsPerChild requests, the child process will die. If MaxRequestsPerChild is 0, then the process will never expire.

MaxRequestsPerChild is the number of requests before the child dies, MaxClients is the maximum number of concurrent connections, 30 is more than enough for a 512, I tend to set it lower.

Basically if you have 30 active requests and someone requests another one then that will be queued for the few milliseconds it takes for one of the requests to finish.

60ms per request seems fine. Of course it depends a lot on network latency.

Your setup seems decent enough and if you're not ooming with 30 max clients I wouldn't worry too much, how many hits/second are you expecting to handle?

@obs:

MaxRequestsPerChild is the number of requests before the child dies, MaxClients is the maximum number of concurrent connections, 30 is more than enough for a 512, I tend to set it lower.

Basically if you have 30 active requests and someone requests another one then that will be queued for the few milliseconds it takes for one of the requests to finish.

60ms per request seems fine. Of course it depends a lot on network latency.

Your setup seems decent enough and if you're not ooming with 30 max clients I wouldn't worry too much, how many hits/second are you expecting to handle?

Thanks for the response obs.

I know I'm skirting pretty close to the ceiling at the moment with 30 max clients. It dies straight away with bench without caching enabled :) But with Quick Cache enabled it runs comfortably with about 50-60MB free.

I currently run a WordPress blog on a shared hostgator account that gets approx. 500 visits per day but does spike up from time to time so I think my current vitals will be fine with it but I'm really know into pure curiousity territory and looking to max the number of reqs/sec for future scalability. Do you think nginx as a proxy in front of apache will bump up the reqs/sec further?

@Pryon:

The MaxClients directive sets the limit on the number of simultaneous requests that will be served. Any connection attempts over the MaxClients limit will normally be queued, up to a number based on the ListenBacklog directive. Once a child process is freed at the end of a different request, the connection will then be serviced.

The MaxRequestsPerChild directive sets the limit on the number of requests that an individual child server process will handle. After MaxRequestsPerChild requests, the child process will die. If MaxRequestsPerChild is 0, then the process will never expire.

thanks Pryon for the useful info re: ListenBacklog

@edbloom:

Do you think nginx as a proxy in front of apache will bump up the reqs/sec further?

Yes. Although I'd ditch apache all together if you go to nginx so you don't have to manage two web servers.

Also consider setting caching headers so that repeat visitors don't have to reload all the static images/pages again.

@obs:

@edbloom:

Do you think nginx as a proxy in front of apache will bump up the reqs/sec further?

Yes. Although I'd ditch apache all together if you go to nginx so you don't have to manage two web servers.

Also consider setting caching headers so that repeat visitors don't have to reload all the static images/pages again.

Cheers obs - I'm going to setup another node running pure nginx over the weekend and will compare numbers. Definitely will cache headers too.

I'd recommend taking a look at php-apc as well if you haven't already. Having an PHP opcache installed and available massively increases PHP's performance.

@Obsidian:

I'd recommend taking a look at php-apc as well if you haven't already. Having an PHP opcache installed and available massively increases PHP's performance.
so i keep hearing but I have installed it and haven't seen a massive performance improvement. It's definitely installed and running correctly but perhaps I've not tuned the APC settings correctly.

@edbloom:

@Obsidian:

I'd recommend taking a look at php-apc as well if you haven't already. Having an PHP opcache installed and available massively increases PHP's performance.
so i keep hearing but I have installed it and haven't seen a massive performance improvement. It's definitely installed and running correctly but perhaps I've not tuned the APC settings correctly.

A huge part of what it does is memory and exec time reduction.

Make sure you're allocating it a healthy amount of memory, otherwise it won't have any room to store the compiled code and it'll keep needlessly dumping cached data that's still frequently used.

@Obsidian:

@edbloom:

@Obsidian:

I'd recommend taking a look at php-apc as well if you haven't already. Having an PHP opcache installed and available massively increases PHP's performance.
so i keep hearing but I have installed it and haven't seen a massive performance improvement. It's definitely installed and running correctly but perhaps I've not tuned the APC settings correctly.

A huge part of what it does is memory and exec time reduction.

Make sure you're allocating it a healthy amount of memory, otherwise it won't have any room to store the compiled code and it'll keep needlessly dumping cached data that's still frequently used.

cheers Obs - er I mean Obsidian! or is that you Obs in disguise :)

I've increased memory assigned to APC and it's not fragmenting much now - I'll keep tweaking it and see how I get on.

@obs:

Not me!
just checking :)

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct