Lua garbage collection question

I’ve read somewhere that:

If there are no references to something, LUA gc will delete it.

But i feel like the following is, either not enough or bad practice:

local NCC = Instance.new("NoCollisionConstraint")
NCC.Part0 = Hitbox
local T1 = {NCC}

T1 = {}

Do i destroy the table values one-by-one, or does setting the table empty make the LUA gc delete it?

Sorry if this is dumb.

From my knowledge.

empty tables aren’t deleted but stored as if they are normal values.

For example if you print T1 the output will be an empty table and not nil

No, i was talking about the values in the table.
Sorry if i wasn’t clear.

Okay i know that, but if a constraint is being used that’s stored only in the table, will setting the table to empty destroy the constraint?

GC exists around what kind of references exist. You aren’t really going to see weak Lua reference except when something goes out of scope or it becomes declared weak from inside of a weak table.

In your example “NCC” will still exist because regardless of what you do to the table a strong reference still exists at the top of the code (the code ends after, which means it will be GCd). Also you aren’t “clearing” the table exactly, what you’ve done here is destroy the strong reference to the old table which will be cause for GC eventually. Setting a reference to nil does not immediately free that memory.

1 Like

So…:

local T1 = {}

function Store()
	local NCC = Instance.new("NoCollisionConstraint")
	NCC.Part0 = Hitbox
	local T1 = {NCC}
end

wait(1)
T1 = {}

If i understand correctly, this will trigger the gc to delete NCC right?

So this is going to bump into some walls of “how Roblox handles GC” versus “how Lua handles GC”. I may not be able to give you an exactly correct answer but I will try to elaborate.

Firstly, you aren’t going to trigger GC, the function for that is collectgarbage and it is deprecated on Roblox. GC in Lua 5.1 is incremental and runs mark and sweep collection. It runs based on memory allocation (aka a certain amount of memory becomes allocated, a certain amount of collection happens).

The biggest thing here is that I really can’t tell you if this object will be deleted because you haven’t given it a parent and I don’t know how Roblox works internally when no references exist to an object with no parent. What I can tell you is that this code itself will no longer have access to it. This is difficult to explain using Roblox objects because they manifest inside of the game’s root itself and will basically hold strong reference through that. Let me explain using a table instead of an object.

local a = {}
local b = {}
a[b] = true
b = nil
task.wait() -- forces garbage collection because GC on Roblox runs cyclically
print(a)

>> {...} 
-- the memory address that our original b reference points to still exists because table referances are strong by default.

Now what if we use a weak table and force the only remaining reference to be weak.

local a = {}
local meta = {__mode = "k"}

setmetatable(a, meta)

local b = {}
a[b] = true
b = {} -- overwrite b referance to a new memory address

task.wait()

print(a)

>> {}

We see collection in the second code chunk because all referances became weak, tables hold strong references by default. GC works a little differently when working with objects that are equally available through your game environment. Holding no reference to something doesn’t mean that it doesn’t exist the way it does in raw Lua.

gc doesn’t technically delete referances how you seem to think it does, yes those referances will be non-existant through collection or through setting them nil but they are referances not objects. Objects take memory and are subject to GC. “NCC” is just a name that you have given to a memory address.

3 Likes

That’s what happens. The GC will eventually (not instantaneously for performance reasons) recycle, first the table and then its elements.

However, there are some exceptions that are basically engine stuff. For example instances. The engine keeps internal references to the instances, so for these to be recycled it is necessary to call its Destroy() method.

In this case NCC will continue to exist in memory until the game ends.

2 Likes