Garbage Collection and Memory Leaks in Roblox - What you should know

This is inaccurate. do-end creates a new scope just like if then-end and any other thing that opens a block. The local limit is per function not per scope, and please stop citing the Lua source as your source because spreading misinformation and citing the Lua source is going to confuse beginners into thinking you are right.

1 Like

I’m aware but that wasn’t my point regarding do-end. What I really meant was that do-end still shares the same stack, it doesn’t actually create a new one. If you allocate 199 variables, and then allocate 1 more variable in a do-end scope, you would exceed the local limit limit. Sorry for my bad wording there.

how fast, and how consistent is garbage collector between each collection?

1 Like

It will probably vary greatly on a case by case basis. I suggest trying the microprofiler and studio profiling tools to see if it’s affecting performance.

2 Likes

I think it’s nice to add that weak tables if used too much or with many values has some impact on performance, but you’re most likely to be just fine.

AFAIK, garbage collection happens every frame, somewhere in between RunService events, in that process it will clean up some of the values that have no strong references, and it will keep cleaning as cycles pass. Garbage collection doesn’t happen at all once.

The time that the object has existed seems to affect how long it takes to GC as well.

1 Like

If I do
a, b = 5, workspace.Part
table = {a, b}

table = nil

would it be the same as
table = {5, workspace.Part}
table = nil ?

Not really, you still have the two variables a and b that aren’t set to nil in the first snippet.

If it happens, is there a way to restore memory that was resetted like ingame data?

Garbage collection will not remove memory that is in use, garbage collection is about removing memory that is not in use. It means that if you get rid of a value completely, you can’t use that value anymore, so Roblox shouldn’t continue to reserve memory for it.

1 Like

Oh so if my game faced data loss, any way I can reverse the data?

If your game faced data loss it wouldn’t have anything to do with garbage collection. Memory & DataStores are two very different and unrelated things.

4 Likes

hello friend thanks for the amazing tips however due to my self-taught english I don’t quite get everything so I just got a few questions, script in startercharacterscripts:

local collectionService = game:GetService"CollectionService"


local character = script.Parent
local humanoid = character:WaitForChild"Humanoid"
local ObjectsToPrint = {}


humanoid.Died:Connect(function()
   for index,Value in pairs(ObjectsToPrint) do 
         Value = nil
         if ObjectsToPrint[Value] then 
            ObjectsToPrint[Value] = nil
         end
   end
   ObjectsToPrint = nil   
end)

local event  = Instance.new"BindableEvent"
event.Name = "Random"
event.Parent = character


event.Event:Connect(function(actionString, informationTable)
      if actionString == "AddTableObjects" then
          if collectionService:HasTag(character,"Printing"..informationTable.Name) then return end 
          collectionService:AddTag(character,"Printing"..informationTable.Name)

          if not collectionService:HasTag(character,"Printing") then 
                collectionService:AddTag(character,"Printing")
          end

            if not ObjectsToPrint(informationTable.Name) then 
                  ObjectsToPrint[informationTable.Name]= {}
            end 

            ObjectsToPrint[informationTable.Name].Word = informationTable.Word
            ObjectsToPrint[informationTable.Name].Delay = informationTable.Delay

            task.delay( informationTable.Delay , function()
                    local number = 0 
                    for index,Value in pairs(ObjectsToPrint)
                         number+=1
                    end 

                    print(ObjectsToPrint[informationTable.Name].Word)
                    ObjectsToPrint[informationTable.Name] = nil
                    number -= 1

                   collectionService:RemoveTag(character,"Printing"..informationTable.Name)

                   if number <= 0 then 
                         collectionService:RemoveTag(character,"Printing")
                         print"Printed everything in the table."
                   end 
            end)
     end
end
--other scripts
for i = 1,5 do
   character.Random:Fire("AddTableObjects", {Name = "Example_"..i, Word = "Hello_"..i , Delay = .5})
   task.wait(Random.new():NextInteger(1,5)
end

this is a poorly constructed example of a code i use, apologies for any mistakes or anything, writing here is weird, i use it for things such as “AddSpeed” to change humanoid walkspeeds depending on priorities and stuff…anyway is there anything else to be cleared here when the character dies? as much as I understand this is everything i need to clear right, set the table to nil again, correct me if im wrong please im getting scared this stuff is stacking i have about 12 of those tables and 12 of those if statements(1 if 11 elseifs) per character spawn as you can see below, they mostly have that same code base, for different things, jumppower, walkspeed, autorotate, ragdoll…etc.
image

if you ask why i use the external table in the example its because sometimes i need to remove something from the table before the delay is up, its different in my case i hope you can understand the analogy, thanks friend

I’ve tried to use this to test some cases but I don’t think I’m doing it correctly. Can you provide better examples of how this is used please?

The time at which things GC isn’t consistent, and isn’t gauranteed to change, so the only way to really utilize this is to poll it. It’s not practical or useful except for testing.

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

local function isReferenced()
	return ref[1] -- ref[1] can be GCed and if it does this will be nil!
end

ref[1] = {someValue = 123}

task.spawn(function()
	-- Each frame, check if the value has GCed
	while isReferenced() do
		task.wait()
	end

	print("Value has GCed")
end)

i’m still learning garbage collection, would doing this be an issue (example)?

script.Parent.Event:Connect(function()
    local AllClear = true
    for _,plr in ipairs(Players) do
       if plr.Clear.Value == false then
          AllClear = false
          break
       end
    end
    if AllClear then
       -- other stuff
    end
end)

Testing GC in a ServerScript and pressing run does not seem to work