Hello, I am currently experimenting with memory leaks. The objective of the experiment is to test how to properly dispose of dictionaries and tables without having Untracked Memory blow up. The experiment is a dictionary with tables whose values are random numbers, to simulate large amounts of data inside a dictionary, as well as to make changes in memory more visible. The experiment was run on a live server, not Studio. My question is how do you get rid of untracked memory, and if you cant, how do you remove tables without it going to untracked memory? Below is the results of my experiment
wait(10)
local S = game:GetService("Stats"):GetTotalMemoryUsageMb()
local Dictionary = {}
print("filling dictionary")
for i=1, 1500000 do
Dictionary[tostring(i)] = {math.random(),math.random(),math.random(),math.random(),math.random()}
end
local F = game:GetService("Stats"):GetTotalMemoryUsageMb()
wait(1)
print("yeeting dictionary")
Dictionary = nil
print("Start ".. S)
print("Dict Fill " .. F)
print("End ".. game:GetService("Stats"):GetTotalMemoryUsageMb())
print("Setting to false")
wait(1)
Dictionary = false
print("End ".. game:GetService("Stats"):GetTotalMemoryUsageMb())
wait(600)
print("First 10 minutes is over.")
print("End ".. game:GetService("Stats"):GetTotalMemoryUsageMb())
script:Destroy()
wait(10)
do
local Dictionary = {}
print("filling dictionary")
for i=1, 1500000 do
Dictionary[tostring(i)] = {math.random(),math.random(),math.random(),math.random(),math.random()}
end
setmetatable(Dictionary,{__mode = "kv"}) -- Sets the entire table as a weak table, allowing garbage collection of the table to be possible
end
print("done")
Thanks to this post for the information I needed, setmetatable by itself didn’t work, I waited 10 minutes to be sure and it did not. Wrapping it in a do end made the table get GCed much faster
Yep! That would be because you are still holding a reference somehow.
If you think about the entire script like its in a do end block, you can sort of see why that might be the case.
The reason the metatable isn’t working is because the values are numeric, meaning weak references don’t matter, so, setting the metatable in that case does nothing.
Garbage collection takes a while to happen sometimes, at most about 20 seconds from my testing, its not instant at all, so, generally you just want to make sure your table can be GCed.
do end blocks are a good way to be perfectly sure you’re not going to run into issues, because it isolates stuff.
Here’s an example of how you can use a do end block to ensure stuff can GC properly:
local someValueToExport
do
local function someHelperFunction(...)
-- Stuff
end
local someTableOfStuff = {...}
someValueToExport = someHelperFunction(someTableOfStuff)
end
As soon as the do end block ends, the locals in it are freed and eventually will GC.
It really mostly comes down to the engine knowing when you aren’t using values. In the case of numbers and strings, I think the engine assumes you’re using them for whatever block they’re a part of.