Question about garbage collection with events

Would variable A be garbage collected? Would test()'s stack frame be deleted? More broadly, is there any memory footprint remaining?

function test()
	local A = {"lots", "of", "data"}

	workspace.Part.Touched:wait()
end

spawn(test)
wait(1)
workspace.Part:Destroy()
3 Likes

I’m not at home to test right now, but here’s how you’d check:

local garbage = setmetatable({}, { __mode = "v" })

local function test()
    local temp = {"temporary"}
    table.insert(garbage, temp)
    workspace.Part.Touched:wait()
end

spawn(test)
wait(1)
workspace.Part:Destroy()
wait(4) -- arbitrary number, enough for the gc to do its job
print(#garbage) -- If 1, then the memory is NOT cleared. If 0, the memory IS cleared. 
9 Likes

It printed 0, which means it is being garbaged collected, which means the stack frame is being cleared. Thanks @Kampfkarren!

1 Like

For future reference; the variable is going out of scope (temp in this case, or A in the original). Once something loses all its references, it’s free for the garbage collector to yoink up, and in both examples, all references are lost once it goes out of scope when returning from the function. Kampf’s example retains a reference, but it’s a weak one, so it’s ignored.

Note that variables used as upvalues may still have references, or might eventually get copied to a different location once the function that uses it goes out of scope too.

2 Likes

The part that remained uncertain, however, is whether this function actually goes out of scope since the :Wait() could be indefinitely (there is code yielding till the event is fired but the connections to the event are cleared). That bit would rely entirely on how the disconnection of events from :Destroy() is handled. (assuming the part isn’t touched before being destroyed)

2 Likes

When the function finishes running or the thread is garbage collected there should be a guarantee of everything it had a reference to losing said reference. The function on the stack would lose its only reference, which then gets collected, and then the variable loses the reference, so it too is then collected, but the thread needs to either reach the end (RETURN on its outermost function), have yielded for long enough (I remember someone mentioning this gc’d in Roblox), or have the function the variable is in RETURN too. At least, I assume this is what you’re referring to.

While the timing is uncertain, the result should not be.

2 Likes

Like with everything else, variables and objects hang in memory until they are marked as free memory when Lua or the engine believes it is not being used. No matter what variables you got or what objects they are associated with, if they are not being used in an event or stored in an object or being read/assigned to… etc…
In smarter optimizers, A would not even be defined because it is never used. In this case however it would cease to exist when the function finishes executing.