-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Anyone fancy playing with the Lua GC? #3175
Comments
Looking at the current system, it seems another perversity is that we're going to follow the exponential growth paradigm until we're bumping up against emergency OOMs and then we're likely to get "stuck" there in some cases:
This is especially frustrating since the very reason that we might be riding around with so much memory in use might be the stack (less likely) or string table (seems plausible) or pending finalizers (seems very plausible) that we could get rid of if we weren't doing EGC! I think we should always clamp the credit the GC can give itself to some fraction (half? 3/4ths?) of the available heap (i.e. |
The default Lua 5.1 strategy -- which is to do a full GC every allocation and free is particularly pathological. Pretty much any move to using the incremental GC as it is implemented in Lua gives factors (maybe 3-4×) improvement in throughput. In this light, if strategy A vs strategy B varies performance by 5 or 10% isn't so important. What is more important is that we don't convert apps that used to run successfully into Whilst we will always have some Lua devs who manage to run out of RAM through bad programming practices or simply trying to do the wrong class of app on a ~44Kb RAM device, in my personal experience RAM isn't really an issue for the apps that I tackle once the Lua code is moved to LFS. Most rarely use much more than 20Kb, so RAM use is less than 50%. What I feel that we need is a simple strategy that works efficiently for this ~50% utilisation but slowly degrades into "full GC every allocation" as we near 100% utilisation. Ideally these settings should be pretty robust so that they just work "out of the box" for typical Lua devs. So a couple of thoughts:
I think that we need to play about further on this. BTW, the -ve ON_MEM_LIMIT options is the (yet to be implemented) |
Speaking of Leaving The scenario to avoid is repeatedly slamming into EGC, which I think we can do by clamping the credit calculated by
That game can be modified by Anyway, I'm happy to muck about in the GC some. :) |
The above patch is a good starting point. The CCOUNT deltas are very informative. I'll push through a review copy of the PR tomorrow with Alpha changes to GC tomorrow. |
BTW, there is something definitely a bit hickey about how |
That just sounds like |
Sorry. Didn't answer this one. It's in There are various tuning constants defined:
Also I also note that the 5.3 GC avoids the integrity failures that can occur in 5.1 where an Emergency GC can call a finaliser method which can end up resizing the stack in the middle of GC callback. If does this by not calling the "unsafe" by avoiding running finalisers or resizing the stack during an Emergency GC. |
In doing an Internet trawl on Lua GC internals, I came across Roberto Ierusalimschy's presentation at the 2018 Lua Workshop. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
@jmattsson Johny, this was the issue that I was talking about |
Interesting discussion, cheers. |
@jmattsson I've just dumped a work in progress to Notes on the Lua Garbage Collector in the NodeMCU implemention explaining how the Lua GC actually works. I've still got to add a bit on the Emergency LGC and how we should trigger it on a free heap() threshold rather than allocation failure because the latter doesn't leave any freeboard for device driver and other service mallocs. This is about the only tweak needed, as far as I can see. I've done some forensics on an instrument version with @nwf, you just might be interested in having a browse as well. I recommend that the I've also got some more detailed notes on the internals of |
Do you reckon that a step collection would make sense to bake into our |
Enabling this as a (maybe default) option might be a good idea. As I said I've been playing with |
I've been looking at how the Lua (5.3) GC works on our builds. At the moment it is pretty standard, but I want to tailor it to more our requirements. The standard GC has two tuning settings that you can tweak with collectgarbage():
"setpause"
. The current default setting is 110, which means that once the GC completes a cycle it waits until the memory use has grown by 10% before unpausing."setstepmul"
. The current default setting is 200, but I suspect that we should have this higher say 300 or 400.The patch below adds a little instrumentation so you can see what is going on, but this could be tweaked. Some general comments:
string
,proto
,table
,userdata
, etc.) causes a sweep check and if past the pause threshold then a (partial) sweep is made through the GCObject list to find unreferenced ones.collectgabage()
every allocation.Also note that a full GC is splil into sweeps and the full GC repeats these until no more RAM can be freed. If you are doing GC at the end of every action function, say, then a slightly lightweight approach might be to do a
collectgarbage('step',4)
instead.Anyway if anyone else wants to have a play and get up to speed with how this all works it would really help being able to have an informed discussion about how to tweak this for our default setup.
Thanks Terry
The text was updated successfully, but these errors were encountered: