Garbage collection behavior changed?

I’m curious to know if anyone else is experiencing new garbage collection behavior regarding weak keys/values in tables.

In an older place I have, the following code runs and outputs as expected and prints an empty table.

local a = setmetatable({}, {__mode = "k"})

local key = {}
a[key] = 1
key = nil

task.wait(1)
print(a) -- should be empty '{}'

while true do
	task.wait(1)
	print(a)
end

However, this code now runs differently in newly created places, such as creating a new baseplate place.
a will still contain the key and value and does not get collected by the garbage collector.
This behavior happens on new templates like Baseplate, Classic Baseplate, & Flat Terrain.


But it doesn’t happen on new templates like Laser Tag, Racing, Suburban, Modern City, Village, or Line Runner.

Why is this? Is there some place setting that alters GC behavior?

I’m pretty sure this is because gc doesn’t happen every frame (maybe every few seconds(?)). After a while, the table does get collected and the weak reference is also removed. It will then start printing empty tables.

My best guess is that new places have a smaller memory requirement so the gc isn’t activated as frequently (and so it seems like it doesn’t work). There’s probably a threshold for garbage collection that’s reached faster in larger place files.

According to the Task Scheduler docs page, it shows a ‘Garbage Collection’ step in each frame.


Although it also does say:
“Some tasks may not perform work in a frame, while others may run multiple times.”

I was under the impression that GC happens each frame according to other posts.

Perhaps GC is triggered by something and doesn’t happen each frame like you said.

However, I just went into a really old Classic Baseplate place I have saved under my profile (nothing in it), and the GC happens consistently in every play test.
But it doesn’t happen consistently on new Classic Baseplates, which makes me believe something changed.