Understanding and Troubleshooting PHP-FPM Memory Usage in Linux: Analyzing Top Command Output


1 views

When monitoring PHP-FPM processes using the Linux top command, it's crucial to understand how memory usage is reported. The key columns to observe are:

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
1234 www-data  20   0  462416  10240   5128 S   0.0  0.5   0:00.12 php-fpm

The memory columns in top show:

  • VIRT: Total virtual memory used (including shared libraries)
  • RES: Resident memory - actual physical RAM being used
  • SHR: Shared memory that could be used by other processes

PHP-FPM processes typically show increasing memory usage over time due to:

// Example PHP script causing memory growth
function process_data() {
    static $cache = array();
    
    // This accumulates memory over requests
    $cache[] = str_repeat('x', 1024*1024); // 1MB per call
}

To get accurate memory measurements, use:

ps -ylC php-fpm --sort:rss | awk '{sum+=$8; printf "PID: %s RSS: %s\n", $2, $8} END {print "Total RSS:", sum/1024, "MB"}'

For better insight into PHP-FPM memory usage:

# Install and use pmap for detailed memory mapping
sudo apt install pmap
pmap -x $(pgrep php-fpm | head -1) | less

# Or use smem for more accurate reporting
sudo smem -k -P php-fpm -c "pid user pss"

Adjust these php-fpm.conf settings:

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 8
pm.max_requests = 500  # Restart after 500 requests

To identify PHP memory leaks:

// Add this to your PHP script
register_shutdown_function(function() {
    $mem = memory_get_peak_usage(true);
    error_log("Memory peak: " . round($mem / 1024 / 1024, 2) . "MB");
});

Consider these alternatives to top:

  • htop - Colorized, interactive process viewer
  • glances - Comprehensive system monitoring
  • nmon - Advanced performance monitoring

When examining PHP-FPM memory usage through the top command, several critical columns demand attention:

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
1234 www-data  20   0  456828 102340  18240 S   0.0  0.5   0:00.12 php-fpm7.4

The discrepancy between observed and actual memory usage stems from these factors:

  • RES (Resident Memory): Physical memory actually used by process
  • SHR (Shared Memory): Memory shared with other processes
  • VIRT (Virtual Memory): Total address space allocated

PHP-FPM's memory management involves:

# To get detailed memory mapping:
pmap -x <pid>

# Output example:
Address           Kbytes     RSS   Dirty Mode  Mapping
0000555555554000     132     132       0 r-x-- php-fpm7.4
00007ffff7a00000    1024    1024    1024 rw--- [anon]

For comprehensive memory analysis:

# Install needed tools:
sudo apt install smem

# Analyze PHP-FPM memory:
smem -k -P php-fpm -c "pid user pss uss rss command"

# Sample output:
  PID User     PSS     USS     RSS Command
 4567 www-data 28.4M  22.1M  32.8M php-fpm: pool www

Consider these PHP-FPM configuration adjustments:

; php-fpm.conf optimization
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500

For production environments, implement these solutions:

# Install and configure Prometheus exporter:
wget https://github.com/hipages/php-fpm_exporter/releases/download/vX.X.X/php-fpm_exporter

# Example service file:
[Unit]
Description=PHP-FPM Exporter
After=network.target

[Service]
ExecStart=/usr/local/bin/php-fpm_exporter \
    --phpfpm.scrape-uri "tcp://localhost:9000/status" \
    --web.listen-address ":9253"