Do instances get garbage collected?

local instance = Instance.new("NumberValue") -- note not parenting to anything
instance = nil

-- the numbervalue was never parented to another instance, since it lost all references it gets garbage collected right?
2 Likes

Yes, all objects, such as instances, tables, functions, coroutines, userdata, etc. are eventually going to get garbage collected as long as reference by the time of garbage collection is lost, or object is weakly referenced (look into weak tables).

Garbage collection in Roblox doesn’t happen instantly, as that would represent a huge amount of resources wasted, hence it runs perhaps periodically as well, but more notably, on demand. You can trigger garbage collection by creating a lot of instances/data and deleting them right after.

EDIT.
Here’s an example of how we can confirm garbage collection was successful. I used @Anaminus’ line from another post that is a very handy way to activate the collector (thanks!).

task.wait(3) -- Looks like GC is active when game starts, so we'll wait a little.

local storage = setmetatable({},{__mode = "v"}) -- weak table values

do -- Reference is lost once out of scope.
	local watchedObject = Instance.new("Part") -- not parented anywhere
	table.insert(storage,watchedObject) -- add to table
end
print("Reference lost here!")

-- Line that actively creates objects and happens to trigger Roblox garbage collector.
game:GetService("RunService"):BindToRenderStep("",0,function() end)

repeat task.wait(.1) until storage[1] == nil
print("Watched object was cleared from memory!")
3 Likes

Okay thank you,

But here it says that references to Instances will never be weak. Is this only if they are parented?

__mode metatable only helps you change the mode to weak keys and/or values. That means if element stored in the table is also strongly referenced elsewhere, it’s not going to be garbage collected, but otherwise, table itself is referencing the object only weakly, which doesn’t stop the collection.

If part is parented, it exists in workspace, so it’s not subject to garbage collection, as opposed to objects that only reside in memory without parent, and are not referenced anywhere.

In the above example, since watchedObject is created inside do-block and not parented, all strong references are lost immediately after that limited scope ends.

Yes but it says that a reference to a Roblox Instance will never be weak.

So if you do the above example will storage[1] be weak or strong?

There’s a distinction that needs to be made. The data of an instance is stored internally in the engine. Whenever a Luau VM access the instance, a userdata is created to facilitate access to the instance (via properties, methods, etc). This userdata is reused once created, allowing it to be used as table keys. When we say that instance is garbage collected, it is this userdata within the VM that is collected by the VM. The actual underlying instance is handled elsewhere.

Consider the following diagram:

1

The Workspace instance is made accessible to the VM through the workspace global variable, which points to the Workspace userdata. Let’s say that the VM runs model = workspace:FindFirstChild("Model") to get the child Model instance. Because a userdata for Model does not exist, a new one is created.

2

What happens when the reference to the Model userdata is removed (e.g. model is set to nil)?

3

There are no longer any strong references to the Model userdata, so when the VM’s garbage collector runs, that userdata is removed. The same would happen if the userdata were referred to by a weak table:

4

Even though the userdata is collected, the actual Model still exists internally, because it is connected to the DataModel:

1

Once again, let’s run model = workspace:FindFirstChild("Model") to get a reference. But then, let’s also run model.Parent = nil to remove the Model from the DataModel.

5

Now the only thing keeping the Model alive is the Model userdata, and the only thing keeping the userdata alive is the model variable. Let’s run model = nil again:

6

The userdata is collected as usual. In the next step, the engine sees that it has some instances that are neither connected to the DataModel, nor referred to by a VM:

7

This causes the engine to free the memory allocated for the Model, which is basically like removing it:

8

As for what the documentation says, it is likely a misinterpretation of the system that I described above. I think that whoever wrote it was trying to convey that an instance with a weak reference may still exist even though it appeared to be garbage collected.

31 Likes

garbage collection is common among Object Oriented Languages, lua in this case.