Php – Apache Start Servers, Min/Max Spare Servers Ram Consumption Influence

apache-2.2memory usageperformance-tuningPHP

I have a 1gb ram VPS.
If I stop apache I have 400 mb ram free.
So the max clients should be (total ram – used ram) / max_service_ram_consumption = 400 / 31.
So MaxClients should be 13.

These are the definitions:

StartServers: number of server processes to start
MinSpareServers: minimum number of server processes which are kept spare
MaxSpareServers: maximum number of server processes which are kept spare
ServerLimit: maximum value for MaxClients for the lifetime of the server
MaxClients: maximum number of server processes allowed to start
MaxRequestsPerChild: maximum number of requests a server process serves

I'm using prefork (apache default).

My config is this one:

Timeout 30
KeepAlive Off
MaxKeepAliveRequests 100
KeepAliveTimeout 2

<IfModule mpm_prefork_module>
    StartServers          3
    MinSpareServers       3
    MaxSpareServers       10
    ServerLimit           50
    MaxClients            50
    MaxRequestsPerChild   1000
</IfModule>

The default value for StartServers and MinSpareServers was 5. I changed it to 3. I can't see any difference in memory consumption. I also changed MaxClients from 150 to 50. And I limited MaxRequestsPerChild to 1000. (default was 0 – unlimited).

Please tell me how StartServers, MinSpareServers and MaxSpareServers influence ram consumption. And why it will be better/wrong to have lower/higher values. I know that these values influence performance also. But I can't find anywhere a good apache ram consumption calculator.

How to configure the apache.conf in order to be able to have around 50/100 max users?

Best Answer

You are on right track. Here are some things which should help you figure out remaining details.

You need detailed monitoring of Apache on all stats provided by mod_status

  • "_" Waiting for Connection
  • "S" Starting up
  • "R" Reading Request
  • "W" Sending Reply
  • "K" Keepalive (read)
  • "D" DNS Lookup
  • "C" Closing connection
  • "L" Logging
  • "G" Gracefully finishing
  • "I" Idle cleanup of worker
  • "." Open slot with no current process

Memory is always scarce, if you check all VM providers basically charge VM price based on size of memory you get. So be mindful when you spend it.

You can define ServerLimit (needs apache stop/start to redefine) and then use MaxClients (which can be adjusted with restart) to set maximum value your server will be able to handle. These values are there to protect someone from internet to exhaust your servers resources. If you calculated you can have 13 threads; 13 it is.

See what is your usage pattern over some period of time and adjust StartServers to be at average usage. So you will start with something that is close to average usage; and if web server needs to serve more requests it will spin up few more workers. Volume of those will be controlled by ceil value of MaxClients and

  • MinSpareServers
  • MaxSpareServers

So you don't want to instantly spin up ton of workers if rise in your traffic is small; you would rather want to spin up worker or two to avoid wasting memory on bunch of additional workers that will probably not be used. It takes MaxRequestsPerChild for spawned process to be destroyed and then based on usage Apache will decide if it needs to start new one to replace old worker.

Regarding MaxRequestsPerChild, you want to avoid 0 here; while it is a good idea to keep things cached in memory for performance, you don't have memory to spare for that. Having lower number something like 1000 or 2000 here is likely better option than default 10000 because recycling workers after serving less HTTP requests will limit their lifetime in which they gradually grow in terms of memory usage. So recycling these sooner rather than later will save you some memory.

As for user count; it depends... if your users are going to be hitting web server nicely throughout the day or is everyone going to need web server at the same time. You need to monitor (graphs and stuff) memory, apache, cpu usage and other system health figures and examine those when you try to come up with way to make things run smoother because there is no general recipe to make things better; it depends a lot on use case and usage patterns.

On memory usage of Apache, this is a tricky problem. Each Apache thread has access to certain portion of memory. This accessible address space is in one part unique to this particular process, whereas some other portions of address space are shared with other Apache threads. So when you want to calculate how much all of them use, you want to make sure you don't account for same address space twice.

Here is my approach to calculate Apache memory footprint; you will likely need to alter first line to fit process name of your Apache because depending on distribution some name Apache process 'httpd' some 'apache2' or possibly something else I can't think of right now...

cmd='httpd'
ps -o size=,rss=,vsz= $(pgrep "$cmd") | awk '
  { size_sum += $1; rss_sum += $2; vsz_sum += $3; processes += 1 } 
  END {
    printf "Size  : %.2f (%.2f) MB\n",size_sum/1024,size_sum/1024/processes
    printf "RSS   : %.2f (%.2f) MB\n",rss_sum/1024,rss_sum/1024/processes
    printf "VSZ   : %.2f (%.2f) MB\n",vsz_sum/1024,vsz_sum/1024/processes
  }'

output should look like

Size  : 178.84 (16.26) MB
RSS   : 118.08 (10.73) MB
VSZ   : 1754.29 (159.48) MB

This is from one of my web servers. First value in each row is total, second in parentheses is per process avg. To explain values, I'll quote ps man page

  • Size : approximate amount of swap space that would be required if the process were to dirty all writable pages and then be swapped out. This number is very rough!
  • RSS : resident set size, the non-swapped physical memory that a task has used
  • VSZ : virtual memory size of the process

What this means for your maths is; processes can potentially grow to VSZ size, they are currently using RSS of RAM which is figure you want to use in your equation when trying to calculate MaxClients/ServerLimit and SIZE is theoretically size your processes could take if completely swapped our due to being idle. Some sources on the topic advocate calculating memory footprint using pmap like

ps -ef | grep httpd | grep -v ^root | awk '{ print $2 '} | xargs pmap -d | grep ^mapped: | awk '{ print $4 }' | cut -dK -f1 | awk '{ SUM += $1} END { print SUM/NR }'

This should return same value as SIZE we calculated earlier.