I’ve come up with some questions regarding memory leaks that I either haven’t found conclusive answers for or no answers at all. With that said, here are my questions:
When you store instances as indexes in a dictionary then set them to nil, does that clear the reference to the instance acting as the index?
For example, if I store data something like this:
local data = {
[workspace.Part] = {Value = 1, Test = "yes"}
}
And later clean it up like this:
data[workspace.Part] = nil
Does that clear the reference to the instance and allow the index-value pair to be garbage collected? Do you need to use something like weak tables if this doesn’t do it?
Exactly what userdatas get marked for garbage collection? With instances, for example, you have to clear all references and destroy them to have them garbage collected. Does this apply to anything else in any factor?
Relating to the last question, do functions get garbage collected when stored in tables?
For example, a custom event system. Say you add functions to a table to represent connecting an event and later looping through the table and firing them all. If you just leave the functions there not being ran and clear all references to the table do they get garbage collected?
So the thing with lua is unlike serial systems like opengls buffers, when you allocate something in memory with table[index] it just fills out a slot in memory. Any when you set it to nil theres no point in it being there because thats literally the definition in how we delete memory, we set the value to nil. You’ll be fine if u set it to nil
Alright, thanks for confirming. I had read something somewhere on the DevForum explaining that such a practice wasn’t enough (for some reason) and that you had to use weak tables. I wasn’t sure about it, so here we are.
By any chance do you have any answers to some of my other questions?
Are you talking about like the local part of a variable not being removed when you set it to nil? I mean to be honest that data is cleared when you do the end part of a function (or just stop coding cause literally a script is like do end)
do
local a=nil
while true do --creates loop where the end thing will never reach, thus a is still in memory
end
end --If we had no while true do this would get rid of a being part of the function environment
Well, I’m not too worried about if you removed functions from a table or set them to nil. I’m mainly getting at the automatic garbage collection process. The two questions I had listed go together for that purpose.
The reason I ask this is because I think that userdata like numbers get garbage collected automatically and don’t require you to have to set them to nil before they can be marked as such. But compared to instances, you have to clear all references to make sure that the instance can be garbage collected. So basically I’m trying to figure out what userdata do I need to clear references to so they can be automatically garbage collected.
I might’ve mixed up terms in my last post, but to clarify, the destroy method of instances still sets the parent property to nil. But, that’s not exactly what I was getting at. I’m trying to focus on userdatas other than instances.
I mean yes, if an object is set to nil, then all of the object’s properties are set to nil. As for your table there, if the script finishes executing, any tables or variables you had in it should be garbage collected automatically.
Not sure what you mean by this in regards to the conversation.
When the script finishes executing, yes this is true. I don’t think I was clear enough with what I meant though. I think this sums up basically what I’m trying to figure out:
First one, you replied to me saying that the Destroy function set’s the parent to nil. I replied back clarifying that it seems to do that simply because it sets the object to nil, and if the object is not there, then the object’s parent property also is not there.
As for the last part, I think you’re overthinking this. The only thing garbage collection collects are inactive variables, so to mark things manually, all you’d need to do is de-reference them by setting them to nil. There’s nothing more to it than that, it’s that simple.
Yes I am overthinking this, but that’s sort of the point. I’m trying to figure out exactly what I need to clear references to so there is no confusion with garbage collection in my code. While on the surface it is simple by cleaning up “inactive variables” as you put it, it can get a little complex. Instances are a type of userdata. They have special properties in Roblox regarding when they can be marked for garbage collection outside of the automatic sweeps that Luau’s garbage collector runs. By properties, I mean that you need to first destroy the instance, then follow through with all the normal Lua/Luau practices for clearing references and waiting for garbage collection.
But where are rules and behavior for examples like these documented? Are there any other examples when you might need to do further clean up to have something marked for garbage collection like instances?
I’m not sure I understand what you mean by “it” or how “it” gets set to nil. If my understanding is correct, instances aren’t really deleted until they’re garbage collected and “setting it to nil” would imply that it’s getting cleared from memory in some way.
If you had a variable referencing a part like so,
local cool = workspace.Part
then did this,
cool = nil
you aren’t deleting that instance or clearing it. You’re just getting rid of the reference to workspace.Part. For the instance to actually be “removed” you’d need to call destroy and clear any and all references to it. Then, the garbage collector will come around at some point and clear it from memory, finally getting rid of it.
Lua manages memory for you, so setting something to nil and expecting it to be removed from memory isn’t how it works. That’s why clearing the references to it is needed. You need to make sure the garbage collector knows that the given Lua object is OK to get rid of.
If this isn’t what you meant, I apologize for the misunderstanding.
Back to my question I’m trying to get at in my most recent post, I’m trying to figure out all the behavior regarding how this process works, especially in relation to Roblox. What other possible Lua/Luau objects do you need to clean up specially in some manner, if at all?
No, only the value is cleared, but it still remains in memory, it will be cleared when the scope it was allocated in ends.
Does that clear the reference to the instance and allow the index-value pair to be garbage collected? Do you need to use something like weak tables if this doesn’t do it?
Yes, the table holds a strong reference to workspace.Part. Though when the scope ends, that table will be garbage collected since it has no strong references, when that table is cleared, workspace.Part will not have any strong references.
do functions get garbage collected when stored in tables? For example, a custom event system. Say you add functions to a table to represent connecting an event and later looping through the table and firing them all. If you just leave the functions there not being ran and clear all references to the table do they get garbage collected?
Yes, when the table is garbage collected or the function is explicitly set to nil, it will be removed from the table and will be cleared when the scope it was allocated in ends.
Exactly what userdatas get marked for garbage collection? With instances, for example, you have to clear all references and destroy them to have them garbage collected. Does this apply to anything else in any factor?
Yes, except that you don’t explicitly “destroy” them.
local a = "a"
local b = a -- b holds a strong reference to a,
-- SCOPE ENDS
-- a has a strong reference, won be cleared
-- b has no strong references, it will be cleared
-- now a has no strong references, since b was cleared, it will be cleared
I appreciate the correction. To clarify with a couple of things…
I have a ModuleScript in my game that’s just a table responsible for keeping track of buildings and related data. It’s required pretty much everywhere on the server so the table shouldn’t be garbage collected.
Lets say that the index of a index-value pair in this module is an instance and the value is a table containing data. If the table value’s references are cleared up and module[instance] = nil is run, does that mean that index-value pair will be garbage collected even if that scope doesn’t end? If not, I assume you have to use weak tables?
With your last code snippet, is the process described below the supposed end of the scope automatic? Following the logic you explained, they will get “destroyed” but from that example it would appear that it happens without any extra cleanup code?
Lets say that the index of a index-value pair in this module is an instance and the value is a table containing data. If the table value’s references are cleared up and module[instance] = nil is run, does that mean that index-value pair will be garbage collected even if that scope doesn’t end? If not, I assume you have to use weak tables?
No, it will be marked for garbage collection, not immediately garbage collected. They will be garbage collected once the scope they were allocated in ends.
With your last code snippet, is the process described below the supposed end of the scope automatic? Following the logic you explained, they will get “destroyed” but from that example it would appear that it happens without any extra cleanup code?
No, that is exactly how it works, literally all you need to do is mark it as nil, it’s that simple. You don’t need to learn how garbage collection works, all you need to know is how to mark something for collection, and when it runs, both of which have been answered already.
In my game I have an OOP class that is responsible for managing its own instance in that table. The scope where the OOP class is create ends quickly, but I’m pretty sure the OOP class only ends it’s scope when I clean it up (clear any instance references, get rid of the metatable, other various cleanup code segments). If I set that instance index to nil at that cleanup, and that scope supposedly ends, will that index will be cleaned up on the next sweep?
I’m a little unsure where the scope of an OOP class ends.