How do i clean up Instances that are inside of nil without parenting to get around the Destroy function?

when i did this

while wait() do
    local part = Instance.new("Part")
    part:Destroy() --destroy ends up not working because part is already in nil
end

i found out that Destroy dont work on objects that are already in nil because i went into the developer console and turns out theres a memory leak caused by the code above. If i comment out those lines of code, the memory leak doesnt happen and thats how i know the code above is the one causing the memory leak.

while wait() do
    local part = Instance.new("Part")
    part.Parent = game
    part:Destroy() --destroy ends up not working because part is already in nil
end

further evidence supporting that destroy doesnt work when Instance is already in nil is this code above. The memory leak gets fixed if i parent the instance object to something that is not nil first and then i call on Destroy

so how do i clean up Instance without using parenting to get around the fact that destroy doesnt clean up any Instance whos parent is already nil or is this a problem with roblox and there is in fact no way to do what i want without getting around?

You may want to use debris service for this

I have tested out a similar code piece, it seems to work fine with no memory leaks jumping to 0.030 MB before dropping down to 0.

debug.setmemorycategory("Part creation then destroy test")

local running = true

while running do
	wait()
	for i=1, 5000 do
		local part = Instance.new("Part")
		part:Destroy() --destroy ends up not working because part is already in nil
	end
end

The long gap I believe was caused when I took a screen shot which lagged the engine a bit.

Tested twice with changing the wait() position and increasing the number of parts created, similar result

debug.setmemorycategory("Part creation then destroy test")

local running = true

while wait() do
	for i=1, 10000 do
		local part = Instance.new("Part")
		part:Destroy() --destroy ends up not working because part is already in nil
	end
end

yeah your right. I didnt test it long enough. It seems like roblox is doing automatic gc after waiting around for a good minute or two. Destroy still do nothing to instances already in nil. After testing for 15 minutes +, the code i showed will cause a memory leak for brief moment before roblox realizes those objects are useless and do their automatic gc. Roblox does automatic gc with or without destroy

2 Likes

Instances still get kept in memory if there’s a strong reference of it kept in a closure. For example, the Part in the following code will never be cleared due to it being referenced in the callback for RunService.Heartbeat.

local Part: Part = Instance.new("Part")

game:GetService("RunService").Heartbeat:Connect(function()
	print(Part)
	Part.Position += Vector3.yAxis
end)

task.delay(3, game.Destroy, Part)

To make sure Instances get properly cleared, you should disconnect any RBXScriptConnections that reference it even indirectly.

local Part: Part = Instance.new("Part")

local OnHeartbeat: RBXScriptConnection = game:GetService("RunService").Heartbeat:Connect(function()
	print(Part)
	Part.Position += Vector3.yAxis
end)

Part.Destroying:Connect(function()
	OnHeartbeat:Disconnect()
end)

task.delay(3, game.Destroy, Part)

Remember, this only applies if you using a connection of a signal outside of the Instance. All connections to an Instance are immediately disconnected once said Instance is destroyed.

1 Like