Does the following contain a memory leak?
local Tween = TweenService:Create(Part, SomeTweenInfo, SomeTweenGoal)
Tween.Completed:Connect(function()
Part:Destroy()
end)
Tween:Play()
Does the following contain a memory leak?
local Tween = TweenService:Create(Part, SomeTweenInfo, SomeTweenGoal)
Tween.Completed:Connect(function()
Part:Destroy()
end)
Tween:Play()
EDIT: Please see the post by @Razor_IB for the right response, which means the answer you are looking for is no. If you want to get the total memory in use by Lua, you can use gcinfo(). I tested both Razor’s function (which I can confirm prints false), and also called the tween function repeatedly with this code:
local TweenService = game:GetService"TweenService"
local SomeTweenInfo = TweenInfo.new(5)
local SomeTweenGoal = {}
SomeTweenGoal.Position = Vector3.new(50, 10, 0)
local Tween = TweenService:Create(game.Workspace.Part, SomeTweenInfo, SomeTweenGoal)
Tween.Completed:Connect(function()
game.Workspace.Part:Destroy()
print("Completed: ", gcinfo())
end)
-- Tween:Play()
while true do
wait(10)
local part = Instance.new("Part")
part.Name = "Part"
part.Anchored = true
part.CanCollide = false
part.Parent = game.Workspace
Tween:Play()
print("Loop: ", gcinfo())
end
And after you run this code, you will see the amount of memory being used by Lua is constant. (You may get an extra KB after the very first print statement, and I don’t know why that is off the top of my head, but it is steady after that.
I suspect it would create a memory leak, yes, although I wouldn’t expect it to be very large.
I am not 100% certain, but this is my reasoning:
The Tween variable is created in the script’s memory and connected to the event function. That variable, even if its part references gets modified or deleted, still exists in the memory of the script. The Part variable is a reference, and references are stored as such. (The ObjectValue comes to mind for me.) If I delete the value of an ObjectValue, the ObjectValue itself does not also then delete itself. To further illustrate this, when you reference a no longer existing instance in a script, you get an error stating the distance does not exist, not an error saying that variable containing a reference to that instance no longer exists. I would expect the same to be true with tweens or anything else for that matter.
To my knowledge, there is no code that specifically checks only tweens to see if its part value got changed.
The only time I have personally seen such behavior, (outside of a script,) is when a model has all of its children parts/models deleted, and at that point the model will delete itself rather than remaining as an empty model.
As a simple experiment, maybe you could see if that script still shows as running after the tween is complete (even if its usage is at 0%) in the running scripts window in studio. Another good test might be to run 1 million instances through the same function/script and to and see if memory starts building up.
To avoid this issue entirely, I would recommend either disconnecting it like you said, or parenting this script to the part that is being tweened. That way, you know the script is being deleted for certain.
You’re also creating a new function value each time the Tween.Completed event is fired although this does eventually get cleaned during the next garbage collection cycle.
Would garbage collection get it if it’s still connected to the event?
Since the function is just a one and done, yes when its execution finishes during the next garbage collection cycle it will be collected. As I mentioned above each time the event is fired a new function value is created and ran.
I see what you mean, thanks! At first I had in mind the event connection itself, rather than when the function is executed and garbage collected when it is called.
This would not create a memory leak because an open function is not a memory leak. However, if youre only looking to get the completed connection once, I would just do it like this. This would remove the need for a function as a whole.
local Tween = TweenService:Create(Part, SomeTweenInfo, SomeTweenGoal)
Tween:Play()
Tween.Completed:Wait()
Part:Destroy()
It shouldn’t cause any memory leak if the script ends there, if the script ends there the “Tween” variable would get garbage collected so all the connections associated to it will be disconnected.You can test it here
local Tween = TweenService:Create(Part, SomeTweenInfo, SomeTweenGoal)
local Conn = Tween.Completed:Connect(function()
Part:Destroy()
end)
Tween:Play()
coroutine.wrap(function()
task.wait(10)
print(Conn.Connected)
end)()
This should print false since the variable gets garbage collected however if you the script doesn’t end you could destroy the Tween object inside the completed event.
local Conn = Tween.Completed:Connect(function()
Tween:Destroy()
Part:Destroy()
end)