-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory leak PHP FPM 8.1 with class entry instances #8646
Comments
Well, most likely there's some code in your application that makes PHP leak memory. Is it possible that you isolate the code causing the problem and then provide a snippet that reproduces the leak? |
All the code runs on the webserver and doesn't run for more than 60 seconds, could it still be due to my code? It's a little tricky trying to isolate everything, isn't there a way to do it without going crazy? A Telegram bot runs on the webserver, so it's mostly curl requests and some redis. |
@davtur19 Normally any memory that PHP allocates per request gets automatically deallocated after the request ends. It's possible that some code in PHP incorrectly allocates memory (persistently instead of request-bound) which does not automatically get freed and thus the memory keeps creeping up. Assuming you can't provide the source code, it's probably easiest to add a |
You might use https://github.com/BitOne/php-meminfo to analyze memory leaks |
No feedback was provided. The issue is being suspended because we assume that you are no longer experiencing the problem. If this is not the case and you are able to provide the information that was requested earlier, please do so. Thank you. |
Maybe this will help anyone. We face same issue, for us, issue was in file descriptors, our app often open/write/close files, as we have by accident used file cache instead of memoryone (bug on our side), and looks like PHP8.1 work differently with open files, as even terminating PHP script did not free ram consumed by file descriptors. Not sure if this is PHP bug or not... |
I tried adding these parameters to the fpm configuration, it keeps leaking memory despite restarting the workers. |
I'm going to re-open this as there are some things to investigate. I will get to it after the feature freeze and few other things. Are you actually talking about master process memory? |
@bukka i am not sure if it feature freeze is a little bit late. |
@bukka i cannot answer that to 100% because we can only reproduce the issue in production with many concurrent requests at the moment. But from what i see with an apache benchmark test, the memory is chilling on ~120mb without op cache. Some More info, JIT was not enabled at all time. |
@bukka the problem also occurs with opcache to 0
My config file: php.ini disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,exec,passthru,shell_exec,system,popen,curl_multi_exec,parse_ini_file,show_source,
expose_php = Off
max_execution_time = 60
max_input_time = 60
error_reporting = E_ALL
display_errors = Off
post_max_size = 51M
file_uploads = On
upload_max_filesize = 50M
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
open_basedir = "/code/:/tmp/"
cgi.force_redirect = 1
[opcache]
; Determines if Zend OPCache is enabled
opcache.enable=0
; The OPcache shared memory storage size.
opcache.memory_consumption=128
; The amount of memory for interned strings in Mbytes.
opcache.interned_strings_buffer=8
; The maximum number of keys (scripts) in the OPcache hash table.
; Only numbers between 200 and 1000000 are allowed.
opcache.max_accelerated_files=10000
; The maximum percentage of "wasted" memory until a restart is scheduled.
opcache.max_wasted_percentage=5
; When disabled, you must reset the OPcache manually or restart the
; webserver for changes to the filesystem to take effect.
opcache.validate_timestamps=1
; Enables or disables file search in include_path optimization
opcache.revalidate_path=1
; If disabled, all PHPDoc comments are dropped from the code to reduce the
; size of the optimized code.
opcache.save_comments=0
; Allow file existence override (file_exists, etc.) performance feature.
opcache.enable_file_override=1
; Check the cache checksum each N requests.
; The default value of "0" means that the checks are disabled.
opcache.consistency_checks=100
#opcache.enable_cli=1
#opcache.jit_buffer_size=100MB
#opcache.jit=1235 fpm.conf [global]
error_log = /var/log/php-fpm.log
emergency_restart_threshold=3
emergency_restart_interval=30s
process_control_timeout=5s
[www]
listen = /run/php/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 100
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 35
pm.status_path = /status
ping.path = /ping
access.log = /dev/null
pm.max_requests=1000
request_terminate_timeout=60s |
After more testing, i think we are hitting an other issue in our end. our leak comes from opcache oom restarts. Have to test that in production tomorrow. |
@davtur19 Just to clarify, are you saying that the emergency restart helps without opcache but does not help with opcache? |
actually "helping" with the ram is the pm.max_requests parameter fpm.conf [global]
error_log = /var/log/php-fpm.log
;emergency_restart_threshold=3
;emergency_restart_interval=30s
process_control_timeout=5s
[www]
listen = /run/php/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 100
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 35
pm.status_path = /status
ping.path = /ping
access.log = /dev/null
pm.max_requests=100
request_terminate_timeout=60s |
I tried just emergency_restarts instead of just using max_requests [global]
error_log = /var/log/php-fpm.log
emergency_restart_threshold=3
emergency_restart_interval=30s
process_control_timeout=5s
[www]
listen = /run/php/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 100
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 35
pm.status_path = /status
ping.path = /ping
access.log = /dev/null
;pm.max_requests=1000
request_terminate_timeout=60s |
@davtur19 Are you able to somehow recreate the issue on non prod (e.g. with some testing redis server and load generated by wrk or similar tools)? If you could provide a minimal app (the smallest version where you can see the issue), that would be also great. If you want, you can send me privately whatever version of the app with installation and recreation steps. I think we somehow need a way to recreate it otherwise it might be really tricky to have an idea what's going on. |
@jreklund Yes that works, thanks! I can open the files and I see a trace in time for the memory allocations. Nothing yet stands out to me but it's only 5 minutes of course. Traces like this will show us the persistent allocations, which is where the leak should come from. For future reference: it's possible to also include request allocations by using |
This round I had valgrind running for 9 hours before sending |
Thank you @jreklund I had a look at the graphs (You can use Note that the x-axis is not entirely the same for both PIDs. This is because PID 1681 is the leader process, and 1682 is the worker, and once the leader has started, no more persistent allocations on requests happened in the leader. The peak in the two graphs is the same one, so you can take that as a reference point on the x-axis. Everything left of the peak is startup, and everything on the right is from the memory consumption throughout your run. Did you observe memory leaking behaviour of this run? If yes, that means the problem is somehow not originating from a persistent allocation, and we can give instructions on how to include request memory inside the graphs. If no, then the experiment needs to be run again in a situation where the leak occurs. |
That's a bummer! Valgrind runs in serial and not parallell so it combined both PHP-FPM memory with it's own, so I have no way of knowing if I had any problems in this run, by looking at the processes. Like you stated before it's super slow, so don't really wanna run it in production. 😅 I can make a longer test on our testserver (don't have a custom built PHP there). PHP 8.2 have been running for a week and started to eat up memory there as well. We do have other applications running on that server as well, and some of them require at least PHP 8.1 to run. I did 150k request on PHP 8.0 and 250k request on PHP 8.2 and then left it as is for a week, just serving around 100 request a day. 2023-05-02 - After stress testing both PHP-FPM 2023-05-10 - After waiting a week (do note that PHP 8.0 haven't been used in any application under this week)
|
Weird, so stress testing did not cause a notable increase in memory usage, but just letting natural traffic flow in did cause an increase? |
I crawled parts of our forum and articles, not all of the websites functionality. Only GET request and with no open session (guest). We have the same problem in our CDN (only guests there) and limited amounts of routes make me think it's something in the core routing, so I didn't make a global crawler or make it sign in. Stress testing only made a small difference and just sitting there waiting did all the work. Haven't looked at it all during the week, so don't know when it jumped. We haven't used PHP 8.1 in production / teserserver, only on dev-machines, so I don't know. We usually jump a version 5.6 to 7.1, 7.3, 8.0 and now 8.2. I'm showing the RES column from This is 15 million request on a production server (WEB), after a couple of DDoS attacks. So it can climb higher in PHP 8.0 as well. Naturally it don't build up as fast thought. |
Long time no see! We have now replaced our entire production infrastructure, as our operating system where reaching end of life. I started off by trying PHP 8.2.9 on our four production servers, to see if it where our old servers fault, but after around 12 hours I had to restart the service on our CDN-servers as it started to write to disk, due to lack of RAM. Later on I had to restart our Web-servers as well. I thought it might have something to do with all DEPRECATED messages that where thrown in set_error_handler(), as we failed to specify that DEPRECATED should not be logged in production. We have a filter in that function that silently hide "passing null to string", as that needs an complete application overhaul. Still only been running PHP 8.0 and 8.2 in production. After fixing that logging error, the issue still persisted, so I downgraded to PHP 8.1.22 and that version works perfectly. 🎉 We have tested these versions in production: It may be a GD problem, as the CDN-servers dies first. Or it's fopen/fwrite as they read stored images on disk. Images are only processed/verified on upload on our Web-servers, so just a gut feeling. Don't have a proof of concept code as I haven't been able to replicate it at this time. I have been busy replacing servers, so haven't made any new efforts since my last post. We don't use any new features from PHP 8.1 and PHP 8.2, as it's compatible with PHP 8.0. We may need to setup a production run with Valgrind after all. 😓
|
Without a reproducer or logs it's not possible for us to guess what the problem may be. Be careful with Valgrind in production, it's gonna slow things down incredibly... An alternative is running a bisect between 8.1 and 8.2 in production. Also tedious, but might be a little easier and more reliable. This also has the advantage of finding the commit that supposedly introduced the issue for you. |
Yeah, I figured as much. Just wanted to give you guys an update on the status; that PHP 8.1 works, that's something you inquired on before. By
|
Huh, I thought I replied to this but apparently I didn't.
Yes, I mean a git bisect. After marking a commit good/bad you need to rebuild PHP and test again yes. Note that you might need to do a ./buildconf and ./configure again as well if you jump between merge commits.
I've done bisecting many times before, it works fine even with the merges. Just sometimes needs a ./buildconf and ./configure again. |
I'm not a 100% sure that it's related, however pcntl_fork() seems to leak php-fpm pools on 8.2.
Will leave the forks running in the background, and eventually they detach themselves from the master process and just keep running:
|
@Xmister That's a different issue than this one. Can you please open a new issue for that bug so we can track it in a separate thread (to avoid cluttering this one)? Thanks. |
how are you measuring your php FPM like in the OP? I'm facing something similar (filamentphp/filament#9637) and trying to invesstigate |
I was using: https://github.com/andrew-ld/docker-stats In a few comments below there were also netdata screens: #8646 (comment) |
@davtur19 thanks, unfortunately I don't run my FPM in a docker. Have you guys tried |
@bilogic after the fixes that had been made, I no longer encountered memory leaks. |
@davtur19 thanks, let me try 8.2.12 and can I confirm you are using |
I think I'm experiencing this memory leak with the very latest PHP 8.2.12 on our production server. We were running PHP 7 in PHP-FPM configuration and memory consumption was stable for years. We migrated our app to another server (with only tiny changes to avoid deprecation warnings about dynamic class properties) and we now see the per-process RAM consumption for our pool of PHP-FPM processes creep up over the course of several days until our server is completely out of memory. Restarting the PHP-FPM pool appears to get all the memory back. Our web app is pretty elaborate so I doubt I can replicate it for anyone, but I do have a bunch of data, including an OOM/Killed dump from the syslog, and some lists of processes were you can see the bloated RAM consumption after about a week versus the lean RAM consumption immediately following a PHP-FPM pool restart. I was pretty alarmed to see that PHP 8.1 is going to be closed for bug fixes and this memory leak may not be resolved? |
I'm going to clarify something: the original reported issue, and some related ones have been long fixed. But this issue report has become a general "report your memleak here" issue, which is kinda ok but confusing for people. Without a reproducer or dump it is not clear if the leak is even in fpm, or in an extension. It could even be a leak in a third party extension. @sneakyimp whatever issue you're having is different from OP's. A dump is better than nothing but since it comes from a production system it has no debug symbols so it will be hard to figure out what exactly happened. And indeed, 8.1 is closed for bugfixes. If anyone wants to share a dump, please do so privately via mail. Reminder: never share the dump in public here because a dump usually contains sensitive data like passwords/credentials/private keys. |
@nielsdos Thanks for your response.
I'm happy to provide any detail I have. Thanks for the warning about the dump possibly containing sensitive info. I was aware of this. That said, I don't think the dump i'm talking about is the same thing as the dump you are referring to. I'm no expert but the information doesn't look very sensitive. I just copied it from the syslog. It goes something like this:
EDIT: I tried posting the charts here but they are not showing up. I posted them to imgur here. |
Right, I indeed thought about a different kind of dump. The one you posted is not sensitive indeed. |
@nielsdos It looks like the adjustment to |
Interesting workaround. It probably hides the real issue, or somehow some children aren't properly terminated? I don't know. |
Version 8.2.5 changelog states:
Should this be closed then? |
The original bug reported in this issue was fixed. It was reopened because people use this issue as a generic leak issue thread. |
Sure! If the original problem is solved we should close this and create new issues for anything distinctly unrelated. |
Description
Description
A few months ago I tried to migrate to php8.1 but it had a memory leak, so I stayed at 8.0, the memory leak is still present today, while on version 8.0 no problem, the memory remains stable.
Info
Armbian (Ubuntu 20.04.4 LTS)
Linux roc-rk3399-pc 5.15.25-rockchip64
Docker version 20.10.16, build aa7e414
Docker image not working: php8.1-fpm
Docker image working fine: php8.0-fpm
My dockerfile:
My php.ini
php8.1-fpm memory usage (purple line):

It had gone up to 800MB in a relatively short time without stopping
php8.0-fpm memory usage (purple line):

I don't know what other information to give you because I don't know how to use profiling tools, and I can't test disabling extensions.
PHP Version
8.1
Operating System
Armbian (Ubuntu 20.04.4 LTS)
The text was updated successfully, but these errors were encountered: