-
-
Notifications
You must be signed in to change notification settings - Fork 237
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
Restart worker after configurable number of requests #280
Comments
This can usually be handled directly in the worker script. Here is an example with Laravel Octane: https://github.com/laravel/octane/pull/764/files#diff-5891b628d054a2240185344524af788b4e613e0d24b82ee3b5a52d174ac0daf7R30 As this can easily be done userland, I would prefer to add this to the documentation instead of "bloating" the C or Go code. WDYT? |
There's an argument to be made for either solution. On the one hand you want to keep frankenphp minimal and most PHP developers don't know go, on the other hand most applications will probably need something for mitigating memory leaks. |
I'm testing this change: php-runtime/frankenphp-symfony@main...mathieudz:frankenphp-symfony:max-requests |
If the debug mode is enabled (set the global |
@mathieudz I just tested your code locally and it appears to work (I added the env var in the |
By the way, you should probably use a runtime option instead of a raw en var. |
|
The workers get restarted regularly (e.g. every 100 requests, running with 16 workers), but the memory usage is still increasing over time |
Here's two cents from a different perspective, technical considerations set aside for a moment: I realize that memory leaks are not the only reason to restart, but a maximum memory setting for the worker would be PHP-ish. It would be in line with the various similar settings for maximum POST size, memory usage, timeout, etc. A timeout and reset-on-max-memory-use setting "feels PHP" to me. Ideally resetting after the current workers finish, which probably points to having a threshold to terminate and a second, higher threshold to hard kill. |
@EvanEdwards I guess that we could check the PHP memory usage with memory_get_usage after the explicit garbage collection against a configurable threshold at https://github.com/php-runtime/runtime/blob/1c6ac3dad61b35e126541190232b497ed934c170/src/frankenphp-symfony/src/Runner.php#L45 |
@mathieudz I'm not able to reproduce locally. Could you try the following things:
Also, do you get OOM errors? If it's the not the case, that may be normal behavior, because Go (as PHP) is language using a garbage collector, but unlike PHP it will give back the memory to the system only when the system needs it (Chrome as a similar behavior for instance). A profile will help identifying if it's Go or PHP that has the memory, and if it's intended or not. If you need help to profile, I'll be glad to help, don't hesitate to contact me privately (mail, Symfony Slack, Twitter DM...). |
@dunglas Thanks, I'll look into it when I have some time. |
I'm running two instances. I restarted one to see what the memory difference was. Fresh-ish: 23mb (already up to 178mb serving very low traffic), running 4 days: 350mb. I'm not sure how to debug an already running instance of frankenphp. From what I can tell by dumping memory from Ran a simple script to look for non-zero bytes in 54/178 mb used (fresh) 106/485 mb used (old) -- yes it grew by over a hundred megs in the last 20 mins... Something fishy is going on. |
@withinboredom would you be able to do a profile (see instructions above)? Also, are you using the worker mode? |
If the problem is in C, we can do something like this to see what's going on: https://kirshatrov.com/posts/finding-memory-leak-in-cgo |
@dunglas See attached zip file for the results of http://localhost:2019/debug/pprof/heap of my production environment.
|
Just a side note: I feel that |
@dunglas -- these are docker containers, not worker mode. I'll see if I can get one running in debug mode. FWIW, I will probably be able to change the env while running. I assume Go knows that env vars are mutable and non-thread-safe... but there's one way to find out :evil-laugh: |
We could try this to detect the leak, if it hasn't been fixed in RC3: https://clang.llvm.org/docs/LeakSanitizer.html |
Since the memory is still leaking with the memory patches of a few days ago (it crashing when reaching ulimit limits), I attach the pprof dumps + a history of memory usage (vmem). It's jumping up and down, but still a very clear linear long-term evolution is visible. |
Thanks for the profiles. Could you also sample the C heap using https://github.com/iovisor/bcc/blob/master/tools/memleak.py please? So we'll see where the memory is used. |
@mathieudz According to the profiles, you're still running a version that is not the latest RC. The |
I have updated my docker image again. |
Let's do that then. Thank you very much for your help, it has been very helpful, and I hope that we'll soon fix the leak too. |
As PHP was not designed for long-running processes, memory leaks are not uncommon as they usually aren't an issue. Introducing long-running processes with tools like frankenphp, memory leaks become problematic.
In my case, my application consumes around 1 GB per hour. As mitigation I have scheduled a zero-downtime restart of the application every 8 hours. However, it'd be nice if frankenphp would provide such functionality out of the box. php pm (from where I migrated) provides such a setting.
The text was updated successfully, but these errors were encountered: