Optimizing Apache MaxClients: Calculating Process Memory Footprint for Server Tuning


4 views

When tuning Apache web server performance, determining the correct MaxClients value requires accurate measurement of your Apache process memory footprint. Many administrators make the mistake of looking at just the resident memory size when more comprehensive metrics are available.

The most accurate way to measure Apache process memory usage is through the following Linux commands:

# Method 1: Using ps
ps -ylC httpd --sort:rss | awk '{sum+=$8; count++} END {print "Average RSS:", sum/count/1024, "MB"}'

# Method 2: Using top in batch mode
top -b -n 1 -p $(pgrep -d',' httpd) | grep httpd | awk '{sum+=$6; count++} END {print "Average RSS:", sum/count/1024, "MB"}'

With 4GB RAM (4096MB), assuming 20% overhead for system processes, here's the precise calculation:

Available RAM = 4096 * 0.8 = 3276.8MB
If average process size = 50MB:
MaxClients = 3276.8 / 50 = 65.536 → Round down to 65

The calculated value goes in your httpd.conf or apache2.conf:

<IfModule mpm_prefork_module>
    StartServers        5
    MinSpareServers     5
    MaxSpareServers     10
    MaxClients          65
    MaxRequestsPerChild 4000
</IfModule>

After implementation, monitor memory usage with:

watch -n 5 "free -m && echo '' && ps -eo pid,user,%mem,command --sort=-%mem | head -11"

Adjust MaxClients downward if you observe swapping. Modern Apache versions use MaxRequestWorkers instead of MaxClients with event MPM.

For more precise memory measurement that includes shared libraries:

pmap -x $(pgrep httpd | head -1) | tail -1 | awk '{print $3/1024}'
# This gives private+shared memory usage in MB

Remember to account for PHP memory_limit if using mod_php, as this significantly impacts process size.


When tuning Apache's MaxClients setting, the critical metric is the memory consumption per httpd process. Many administrators mistakenly look only at the resident set size (RSS), but a more comprehensive approach is needed.

To get accurate measurements, use this command:

ps -ylC httpd --sort:rss | awk '{sum+=$8; ++n} END {print "Total RAM="sum/1024"MB"; print "Average per process="sum/n/1024"MB"}'

For a production server under real load:

  1. Restart Apache to get fresh measurements
  2. Run load testing with your typical traffic pattern
  3. Measure memory usage during peak periods

Example output analysis:

# Sample output from 'top'
PID USER   PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
1234 apache 20   0  412m  28m 4568 S  0.0  0.7   0:00.01 httpd
1235 apache 20   0  412m  29m 4700 S  0.0  0.7   0:00.03 httpd

The formula is:

MaxClients = (Total RAM - (OS + other services)) / Average httpd process size

For your 4GB (4096MB) server with 30MB average httpd processes:

# Reserve 512MB for OS and other services
MaxClients = (4096 - 512) / 30 ≈ 119

Configuration in httpd.conf:

<IfModule mpm_prefork_module>
    StartServers         5
    MinSpareServers      5
    MaxSpareServers     10
    MaxClients         120
    MaxRequestsPerChild  10000
</IfModule>

For modern systems using keepalive connections:

# Calculate based on both memory and available file descriptors
MaxClients = MIN((Available RAM / Process Size), 
                 (File Descriptor Limit - 100) / 2)

To check file descriptor limits:

ulimit -n
# For system-wide limits
cat /proc/sys/fs/file-max

Implement regular monitoring with this script:

#!/bin/bash
while true; do
    httpd_mem=$(ps -o rss= -p $(pgrep httpd) | awk '{sum+=$1} END {print sum}')
    total_mem=$(free -m | awk '/Mem:/ {print $2}')
    echo "$(date): $(($httpd_mem/1024))MB of ${total_mem}MB used by Apache"
    sleep 60
done