I’m a member of a development team for a game on which we’re currently experiencing fairly drastic memory management issues - to the point where the UI is disappearing - and I’m only just now starting to glean information on exactly how to prevent leaks and maintain free space. That being said, the research I’ve done hasn’t answered specific questions I have, and thus I hope to find more answers here. Please be patient if I ask anything obvious, I’m just making incredibly sure that I understand how to tackle the problem.
In loops that do not end (our primary game handler runs cyclically) are local variables created within the scope of the loop marked for collection at the end of that particular iteration?
I’ve used while loops to test whether or not scripts continue to run after being destroyed, and I’ve noticed that scripts that are destroyed as a result of their parent container being destroyed do not continue to run, whereas scripts that are destroyed directly (either by themselves or another script) DO continue to run. Obviously, the still-living scripts would need to be cleansed of references to free up memory. But what about the scripts that don’t? Are they actually still running and I’ve been hoodwinked? Or, do I need not worry as they can no longer hold references?
If I create a local variable within a scope that points to an external one, will that reference be cleansed at the end of the scope?
Exactly what sets of circumstances can lead to a leak? I understand connections that are never broken can be one cause, but destroying the object to which they are bound resolves that issue.
I can provide code samples if needed. I’m trying to figure out exactly how I need to go about fixing an entire game’s worth of code, and what I need to change. Some general rule-of-thumbs would be nice.
Local variables refer to a variable that’s defined within the current scope. If you define a variable within a loop iteration, non-terminating or not, it will be cleaned up when the iteration ends. If the local variable’s assignment is a reference to an outside object, the reference will be removed.
When dealing with the cleanup of variables, be cautious: a variable being collected doesn’t mean the value will be cleaned as well. If you’re holding a strong reference to an object, it won’t get collected until all references to the object are lost. There is still a need for the object so it will continue to exist.
A script that stops running effectively terminates and the scope ends, so yes the references would be removed and connections disconnected, among others. Don’t rely on this though and make sure your code employs proper practices for handling variables and such.
A memory leak typically refers to a variable that fails to be cleaned up. There are a couple of resources based on memory leaks and the internet can help you as well. One particularly resourceful thread I’ve found:
Thanks! One last question - do arguments in functions count as variables local to that function for the purpose of garbage collection? For example, if I sent a part to a function as an argument, does the argument in the receiving function that holds a reference to the part get GC’d when the scope of the function terminates?
What types of objects can be garbage collected? Does raw data take up memory - numbers, strings, or userdata values like Vector3’s or BrickColors? What about functions?
Exactly what should I be making sure I set to nil when I’m done with it?
From what I understand, Lua can’t GC any non-nil variable, value, or function. If it exists, and a script says it exists, Lua can’t clean it up. If a script is no longer able to reference things when it stops running, and no other script holds a reference to it, then I guess that’d allow the variables to be garbage-collected.
But I don’t know how to prove that works. Is there a clear-cut way of identifying a leak and where it occurs?
MicroProfiler could be in use. You could name sections of your code using the MicroProfiler and anaylze the memory taken up over time. (Assuming this is on the client)
You could also use the ROBLOX Developer Console which has some pretty useful information regarding the memory usage on the Server and Client. It also can allow you to record activity on the Server using the MicroProfiler and returns the output in a pretty readable format. The files are stored in your logs.