• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 9+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Step-by-Step: Diagnosing PHP-FPM memory consumption per child process on OVH Servers

Step-by-Step: Diagnosing PHP-FPM memory consumption per child process on OVH Servers

Understanding PHP-FPM Memory Limits and OVH Specifics

On OVH servers, particularly those utilizing their “Public Cloud” offerings or dedicated servers with custom configurations, understanding and controlling PHP-FPM memory consumption is critical for stability and performance. PHP-FPM (FastCGI Process Manager) spawns multiple child processes to handle incoming web requests. Each of these processes can consume a significant amount of memory, especially with complex applications or memory leaks. When these processes exceed available RAM, the system can become unstable, leading to OOM (Out Of Memory) killer interventions, slow response times, or outright crashes. OVH’s infrastructure, while robust, still requires diligent monitoring and configuration to prevent such issues.

This guide focuses on diagnosing memory usage *per child process* and provides actionable steps to identify the root cause on OVH environments. We’ll leverage standard Linux tools and PHP-FPM’s own configuration directives.

Initial Assessment: Monitoring Overall Memory Usage

Before diving into individual processes, it’s essential to get a baseline of your server’s overall memory situation. Tools like htop or top are invaluable here. On an OVH server, you’ll typically have SSH access to the command line.

First, ensure you have htop installed. If not, use your package manager:

  • Debian/Ubuntu: sudo apt update && sudo apt install htop -y
  • CentOS/RHEL: sudo yum update && sudo yum install htop -y

Once installed, run htop. Look for the php-fpm processes. You’ll see multiple entries, each representing a child worker. Pay close attention to the RES (Resident Memory Size) column. This indicates the non-swapped physical memory a process has used. If the total RES for all php-fpm processes is consistently high, or if the overall system memory is nearing exhaustion, you have a problem.

To specifically filter for PHP-FPM processes in htop:

  • Run htop.
  • Press F4 (Filter).
  • Type php-fpm and press Enter.

This will isolate the PHP-FPM workers, making it easier to observe their individual memory footprints.

Leveraging PHP-FPM Configuration for Memory Control

PHP-FPM has several configuration directives that directly impact memory usage. These are typically found in the PHP-FPM pool configuration file, often located at /etc/php/[version]/fpm/pool.d/www.conf or a similar path depending on your PHP version and distribution. On OVH, this path is standard.

Key directives to examine:

  • pm.max_children: The maximum number of child processes that will be spawned.
  • pm.start_servers: The number of child processes started when the master process starts.
  • pm.min_spare_servers: The minimum number of idle (spare) processes.
  • pm.max_spare_servers: The maximum number of idle (spare) processes.
  • pm.process_idle_timeout: The number of seconds after which an idle process will be killed.
  • memory_limit (in php.ini): The maximum amount of memory a single PHP script can consume.

While memory_limit caps individual script execution, the pm.* directives control the *number* of processes and their idle states. If pm.max_children is set too high, you can overwhelm the server even if individual scripts are well-behaved. Conversely, if pm.process_idle_timeout is too low, PHP-FPM might constantly be spawning and killing processes, leading to performance degradation.

A common mistake is to set pm.max_children based on available RAM without considering the memory footprint of each child process *plus* other system services. A good starting point for pm.max_children is often (Total RAM - RAM for OS/other services) / Average PHP-FPM Child Memory Usage. However, this requires knowing the average usage, which is what we aim to find.

Diagnosing Memory Usage Per Child Process

To pinpoint which child processes are consuming the most memory, we can use a combination of ps and grep, or more interactively with htop.

Method 1: Using ps and awk

This command will list all running processes, filter for those owned by the PHP-FPM user (often www-data or similar), and sort them by resident memory usage in descending order.

First, identify the user PHP-FPM runs as. Check your php-fpm.conf or www.conf for the user and group directives. Typically, it’s www-data on Debian/Ubuntu systems.

Execute the following command (replace www-data if your user is different):

ps aux | grep 'php-fpm: pool' | grep -v grep | awk '{print $6, $11}' | sort -nr | head -n 20

Explanation:

  • ps aux: Lists all running processes in a user-friendly format.
  • grep 'php-fpm: pool': Filters for lines containing “php-fpm: pool”, which identifies the worker processes.
  • grep -v grep: Excludes the grep process itself from the results.
  • awk '{print $6, $11}': Prints the 6th column (Resident Set Size in KB) and the 11th column (Command name).
  • sort -nr: Sorts the output numerically (-n) in reverse order (-r), putting the largest memory consumers at the top.
  • head -n 20: Displays the top 20 memory-consuming processes.

The output will look something like this:

150320 /usr/sbin/php-fpm: pool www
148760 /usr/sbin/php-fpm: pool www
145200 /usr/sbin/php-fpm: pool www
... (and so on)

The first number is the memory usage in KB. If you see consistently high values for many processes, it indicates a systemic memory issue within your PHP application or its dependencies.

Identifying the Culprit Script or Request

Knowing *which* process is using memory is only half the battle. We need to know *why*. This often involves correlating the memory usage with specific requests or scripts.

Method 2: Using strace (Advanced & Invasive)

strace can trace system calls and signals. While powerful, it can significantly slow down the process it’s attached to and generate a lot of output. Use with caution in production.

First, identify the PID of a high-memory PHP-FPM worker using htop or the ps command from the previous step.

Then, attach strace:

sudo strace -p <PID> -s 1024 -f -e trace=memory,open,read,write,mmap,brk

Explanation:

  • -p <PID>: Attach to the specified process ID.
  • -s 1024: Set the string size to 1024 characters (useful for seeing file paths or arguments).
  • -f: Trace child processes as well.
  • -e trace=...: Specify which system calls to trace. We’re interested in memory-related calls (memory, mmap, brk) and I/O (open, read, write) which can indirectly indicate resource usage or file loading.

Observe the output. Large allocations via mmap or frequent brk calls might indicate dynamic memory allocation patterns. However, interpreting raw strace output for memory leaks can be challenging.

Leveraging PHP’s Built-in Memory Profiling

For more direct insights into PHP script memory usage, enabling Xdebug or using a dedicated memory profiler is the most effective approach.

Using Xdebug

Xdebug can generate detailed profiling information, including memory usage per function call. This is invaluable for identifying memory leaks within your PHP code.

1. Install Xdebug:

pecl install xdebug
echo "zend_extension=$(phpenv which xdebug.so)" >> /etc/php/[version]/fpm/conf.d/20-xdebug.ini

Replace [version] with your PHP version (e.g., 7.4, 8.1). You might need to adjust the path to xdebug.so based on your PHP installation method (e.g., using phpenv, phpbrew, or system packages).

2. Configure Xdebug:

Edit the Xdebug configuration file (e.g., /etc/php/[version]/fpm/conf.d/20-xdebug.ini) to enable memory profiling:

xdebug.mode = profile
xdebug.profiler_enable_trigger = 1
xdebug.output_dir = /tmp/xdebug_profiling
xdebug.profiler_output_name = cachegrind.out.%t-%R
xdebug.max_nesting_level = 1000
xdebug.memory_analysis.enable_trigger = 1
xdebug.memory_analysis.start_with_request = yes

Explanation:

  • xdebug.mode = profile: Enables profiling.
  • xdebug.profiler_enable_trigger = 1: Profiling is only enabled when a specific trigger is present in the request (e.g., a cookie or GET/POST parameter).
  • xdebug.output_dir: Directory where profiling files will be saved. Ensure this directory is writable by the PHP-FPM user.
  • xdebug.memory_analysis.enable_trigger = 1: Enables memory analysis.
  • xdebug.memory_analysis.start_with_request = yes: Starts memory analysis for every request (can be resource-intensive, consider using triggers for production).

3. Trigger Profiling:

To generate a profile for a specific request that you suspect is causing high memory usage, you can add a GET parameter like ?XDEBUG_PROFILE=1 to the URL. For POST requests, you might need to configure Xdebug to use a POST parameter or a cookie.

4. Analyze Profiling Data:

The generated files in /tmp/xdebug_profiling are in Cachegrind format. You can analyze these using tools like KCacheGrind (Linux/Windows) or Webgrind (web-based).

Open the profiling file in your chosen tool. Look for functions or methods that consume a large amount of memory (often indicated by “Inclusive” or “Exclusive” memory usage metrics). This will directly point you to the problematic code sections.

PHP-FPM Process Restart and Tuning

Once you’ve identified the cause (e.g., a specific script, a memory leak, or inefficient code), you can take corrective actions. If the issue is intermittent or difficult to pinpoint, sometimes a well-tuned PHP-FPM configuration can mitigate the symptoms.

Tuning pm.max_children and related settings:

After observing the average and peak memory usage of your PHP-FPM processes (using htop or ps), adjust pm.max_children in your www.conf. A common strategy is to set it to a value that keeps total PHP-FPM memory well below 80% of your server’s RAM, leaving room for the OS and other services.

Example calculation:

  • Server RAM: 16GB
  • Reserved for OS/other services: 2GB
  • Available for PHP-FPM: 14GB (approx. 14336 MB)
  • Average PHP-FPM child memory: 50MB (observed from htop)
  • pm.max_children = 14336 MB / 50 MB ≈ 286

This is a rough estimate. You’ll need to monitor and adjust. Start conservatively and increase if needed.

Consider tuning pm.min_spare_servers and pm.max_spare_servers to balance responsiveness with resource usage. If you have frequent traffic spikes, having more spare servers ready can improve performance. If resources are tight, keeping spare servers low can save memory.

Restarting PHP-FPM:

After making configuration changes, you must restart PHP-FPM for them to take effect:

sudo systemctl restart php[version]-fpm

Replace [version] with your PHP version (e.g., php7.4-fpm, php8.1-fpm).

Conclusion and Best Practices

Diagnosing PHP-FPM memory consumption on OVH servers involves a systematic approach. Start with overall system monitoring, then drill down into individual PHP-FPM processes. Utilize Linux tools like ps and htop for process-level insights, and leverage PHP’s own profiling capabilities (like Xdebug) to pinpoint problematic code. Remember to tune PHP-FPM’s process manager settings (pm.max_children, etc.) based on observed memory usage and available server resources. Regular monitoring and proactive tuning are key to maintaining a stable and performant PHP environment.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Step-by-Step: Diagnosing thread pools deadlock during concurrent ActiveRecord transaction processing on Linode Servers
  • Securing Your E-commerce APIs: Preventing SQL Injection (SQLi) in customized checkout queries in WooCommerce Implementations
  • Disaster Recovery 101: Architecting Auto-Failovers for MySQL and Ruby Deployments on Linode
  • High-Throughput Caching Strategies: Scaling MySQL for Perl Application APIs
  • Disaster Recovery 101: Architecting Auto-Failovers for DynamoDB and Laravel Deployments on DigitalOcean

Copyright © 2026 · Vinay Vengala