Hello everyone, I’d like to propose adding a new configuration directive, tentatively called *pm.max_memory*, to PHP-FPM. This directive would allow administrators to specify a per-child memory usage limit, after which the PHP-FPM child process would gracefully exit or restart. Background and Rationale
In many production environments, especially those handling long-running or memory-intensive processes, *memory leaks* (whether in extensions, libraries, or user code) can slowly accumulate. We already have tools like pm.max_requests that recycle processes after a certain number of requests, but there are scenarios in which memory usage might skyrocket within fewer requests—or memory might slowly climb in a way that doesn’t align well with request counts alone. A setting like pm.max_memory could: 1. *Mitigate slow leaks:* By enforcing a hard memory cap at the process level, ensuring no single worker balloons in size over time. 2. *Provide more granular control:* If certain scripts or pools are known to be memory-intensive, an admin could set a memory limit that’s appropriate for that usage pattern, rather than tying it only to request counts. 3. *Complement system-level controls:* While cgroups and container memory limits exist, a built-in FPM mechanism can be friendlier than a system OOM kill, which might be abrupt and less predictable. Proposed Behavior - A new config directive, *pm.max_memory*, which, if set to a value above 0, indicates the maximum amount of RAM (in bytes) a PHP-FPM worker process is allowed to use (resident set size or a similar metric). - After handling a request, each worker would check its own memory usage. If it exceeds the threshold, it would gracefully exit or be terminated by the master process before picking up a new request. - By default, this setting could be *disabled* (pm.max_memory = 0), so it does not affect existing installations. Implementation Details and Challenges I am not proposing to implement this feature myself—I’m more of a sysadmin and don’t have the necessary C knowledge to patch php-src. However, here are some thoughts on what the implementation might involve: 1. *Measuring memory usage:* Likely via getrusage(), mallinfo() (on some platforms), or reading from /proc/self/statm on Linux. 2. *Graceful shutdown logic:* Ensuring no ongoing requests are abruptly killed, or at least minimizing the chance of partial request handling. 3. *Platform differences:* Some OSes might provide different APIs for measuring process memory usage. We’d need consistent cross-platform behavior or documented differences. 4. *Interaction with pm.max_requests:* If both are set, a worker would exit on whichever limit it hits first (memory or request count). Alternatives - *Using pm.max_requests:* Currently the main workaround to mitigate leaks, but it’s less precise and can’t handle large memory spikes that happen quickly. - *System-level OOM or cgroups:* This approach can kill the entire pool or container, which is often more disruptive than recycling a single worker. Request for Feedback I’m posting this proposal to gather feedback on feasibility and interest. If there’s enough support, I’d be happy to collaborate with anyone who can handle the technical side—writing up a formal RFC on the wiki or working on a patch. If there’s a consensus that this is better handled elsewhere (system-level or container-level controls), or that pm.max_requests is sufficient, please let me know your thoughts. *Key questions*: 1. Would a built-in memory cap be beneficial for a significant subset of PHP-FPM users? 2. Are there any major technical hurdles or objections to this approach? 3. Does anyone have suggestions on how best to measure memory usage accurately and portably across different platforms? Thank you for reading and considering this idea. I look forward to hearing your insights and am happy to clarify or discuss any aspect of this proposal further. Best regards, Sincerely, Arkadiy Kulev (Ark)