Garbage Collection (Issue)

Hello everyone! I hope you are feeling great today.

  1. What do you want to achieve?
    I want to know when an Object has been garbage collected.

  2. What is the issue?
    Lua itself has a __gc metamethod which can be useful to know when your own object got garbage collected, however, is too limited as you cannot know if a thread, function, or an userdata have been garbage collected.

    The only solution to this problem is to store the object in a weak table and check it every frame to see if it’s still there. If is not found in the table you can assume it was garbage collected.

    However; Luau doesn’t provide either the __gc metamethod and a way to perform a garbage collection cycle to know if you have any memory leaks.

  3. What solutions have you tried so far?
    As I said previously, the only solution that there is in Luau is to check if the object is not found anymore in a weak table, but there is an issue. Roblox runs a garbage collection cycle whenever they wish to (when it hits certain levels you know).


Back then I asked something about the __mode metamethod not removing things from the table in time and got this solution: __mode metamethod not working as expected - #3 by Anaminus

The solution is no longer applicable though, I literally have to spam a bunch of BindToRenderStep creating many objects to kinda make the garbage collection system do its job (which is hard as sometimes it takes minutes before doing so). This makes it really hard for me to debug my code whenever I want to test for memory leaks and when I need to know if an object (no instances included) has been destroyed in-game.

Anyone has any other idea of what I could try, because I am sure that if I request such a thing to Roblox using the feature request it will literally be ignored as is something I have always seen Roblox mention in their API Reference as something they don’t wanna do.


Reasons:
1- __gc metamethod removed for security reasons.
2- collectgarbage() just works with the “count” command and not “collect” which performs a garbage collection cycle when called in Lua.
3- Weak tables do not work at all with Instances.


Some people around the community support those 3 things I said by having as the main reason “is not as easy as you think”. If there is no agreement between the community, how can we even achieve something?!

Before you ask me, why I wanna know if an object was garbage collected. Is mainly to perform cleaning with other things. For example, when a thread has been garbage collected I disconnect connections, cancel other threads, and even destroy certain instances.

That said, do you have any other solution to this problem?

1 Like

If you need instances to be garbage collected call Destroy on them and set all of their references to ‘nil’. You can determine when they are collected by calling collectgarbage("count") before and after the above process.

task.wait(10) --Core game elements still loading.

local Workspace = workspace
local Part = Instance.new("Part", Workspace)

local Time = tick()
local Memory = gcinfo()
Part:Destroy()
Part = nil

while true do
	if gcinfo() < Memory then break end
	task.wait()
end

print(tick() - Time) --0.4337623119354248
1 Like

I wasn’t referring to Instances themselves, I am talking about any object like a thread, function, table, or userdata.

The code you also gave me won’t be accurate since on the next frame Roblox could collect things from CoreScript or other things you are not using in the script. In other words, the Instance could not be garbage collected yet, but other things could be collected, causing this to not be accurate.

gcinfo() can even return a higher value as other code could run the next frame causing the Lua memory usage to bump up.


However, in original Lua you could just do:

collectgarbage("collect") --> Run a gc cycle
local Default = collectgarbage("count")

-- Do Stuff --

local Usage = collectgarbage("count")
collectgarbage("collect") --> Run a gc cycle
print((Usage - Default) <= 0)

Having the ability to run a garbage collection cycle would solve this issue, but you can’t do that in Luau sadly.

The code you also gave me won’t be accurate since on the next frame Roblox could collect things from CoreScript or other things you are not using in the script. In other words, the Instance could not be garbage collected yet, but other things could be collected, causing this to not be accurate.

I provided a naive solution because that’s all I could provide (due to Luau’s sandboxing), I wasn’t sure of your use case but you can remove the built-in CoreScripts (which is what I did when running the snippet provided above).