How to avoid high UntrackedMemory?

Is this in one thread though? Is your timer a while loop with waits which call the function of is it some kind of event system? If it’s in one thread you should try setting the reference to nil like I suggested since the thread needs to end to cleanup.

Which reference? All references in the function are set to nil at the end of each use.

Even variables? If so that would cross out my idea

I don’t know if there’s a way that you can avoid it. I just did a test and it’s kind of unsettling. UntrackedMemory was ~86 before running the test and shot to ~260, and never went back down. Here’s the code:

startButton.ClickDetector.MouseClick:Connect(function()
	for i = 1, 500 do
		local newPart = Instance.new("Part")
		newPart.Parent = workspace
		
		newPart = nil --the inclusion of this line has made no difference
	end
end)


stopButton.ClickDetector.MouseClick:Connect(function()
	for i,v in pairs(workspace:GetChildren()) do
		if v.Name == "Part" then
			v:Destroy()
		end
	end
end)

--method two; both have the same results

local parts = {}
startButton.ClickDetector.MouseClick:Connect(function()
	for i = 1, 500 do
		local newPart = Instance.new("Part")
		newPart.Parent = workspace
		
		table.insert(parts, newPart)
	end
end)


stopButton.ClickDetector.MouseClick:Connect(function()
	for i,v in pairs(parts) do
		v:Destroy()
		parts[i] = nil
	end
	parts = {}
end)

Even after clicking the stop button UntrackedMemory didn’t go back down.

2 Likes

Hmm, does wrapping things in event connections change the way it’s garbage collected or are there alternatives? After much testing with my problem, it really seems like there’s nothing wrong with tables. I’m thinking of trying other methods instead of tables because of the massive problems that it can cause.

I don’t know about how the event connections relate to garbage collection but I can tell you that you should make sure to disconnect connections that you don’t need anymore. I don’t think that tables are causing the rise in UntrackedMemory. I’ve noticed UntrackedMemory rising when destroying parts on the server for months now and I’ve tried a lot of different things to prevent it, but nothing works.

It seems to be a problem that’s affected a lot games, including top games, for a while now:

1 Like

Idk if this will help but if destroying blocks is a issue couldn’t people just make a folder in server storage that holds all the destroyed parts in a folder and if it’s for example a block that respawns every so often.

Couldn’t they just move that block back into a different area which would not use :Destroy() and not be going into Garbage collector. If it works it would more likely be a temporary fix.

Also I have a other idea that might work wich is same method but having a bunch of blocks that you need to fill up the mines into a folder and then your script could take from the folder in server storage and place them at appropriate spots and would defeat the purpose of using destroy but it Probobly won’t raise untracked memory because you use the same block each time you generate but you move them in diffirent spots every time you generate so you don’t use Destroy()

I haven’t tried this before but it could work.

This theoretically would fix untrackedmemory, but ultimately doesn’t help the memory level. UntrackedMemory rises as parts get deleted, yes, but memory stays the same. It seems that the problem is worse than just untracked.

I have done a little bit of experimenting and here are the results of my experiment.

  • Don’t use Instance.new(objectName), have a base part which you can call object:clone() on
  • Before you parent something outside of nil, put it into your table, not after

Whenever I use this method, my UntrackedMemory doesn’t increase after I call object:Destroy(). On the other hand, whenever I delete something created with Instance.new, my UntrackedMemory increases substantially. As for why this happens, I can only speculate. I will be doing some more experimentation and will post my updates here.

Update 1:

  • It seems that if you change the properties of the part, the UntrackedMemory starts to increase.

Update 2:

  • This does not work for anything with descendants

Update 3:

  • I have found that it is not ideal to use table.insert, instead you should directly overwrite nil path files using tableExample[i] = xyz
  • Even if you don’t delete the objects, but rather store them inside of a folder and then re-use them, UntrackedMemory continues to change over time. I have gone from 15 → -175 → -328 a few times after running tests with this.

Update 4:

  • With regards to the previous UntrackedMemory tests, after waiting 10 minutes, it still hovers at -328. It is important to note that 50 models with 10 unique parts inside of them are being “deleted” and “recreated” every 5 seconds.

Update 5:

  • After switching to a true online server, after 5 minutes of “deleting” and “recreating” objects in the manner described above, my UntrackedMemory remains at around 90
9 Likes

Maybe this is linked to objects with more objects inside of them? The method I’ve been using follows all of that criteria and still has issues.

1 Like

Based on what I’ve found, this does seem to be the case.

1 Like

Does your UntrackedMemory increase or decrease? That is to say, does it stay positive and continually increase in a positive manner, or does it become negative and continually increase in a negative manner.

Example of positive manner: 10 → 200 → 500
Example of negative manner: 10 → -200 → -500

It would be very beneficial to me if you could let me know.

1 Like

It rises overall, but decreases as more objects spawn. Once the mine resets in this game, the untracked memory goes up quite a bit. The amount it goes down when objects are spawned is much less than the amount it rises, the untracked memory is being replaced by regular memory usage. The overall memory on the server goes up.

I am having the opposite problem

Try using this script when cloning and deleting objects. There is documentation included inside of the modulescript.

Please let me know the results of your tests when using it.

8 Likes

So this stores objects for later use instead of making tons of clones and just deleting them, a neat workaround. Nicely done here; this may be a temporary solution for most cases. For my case, I think it could work. I’ll try this idea out, but it might take a long time to get results since mining in this game I’m developing takes a while to crash the server usually (about two hours).

2 Likes

Amazing, it works! The server memory caps out at large amounts of objects, and never climbs again because no new instances are created or destroyed, only called in or cached. Thanks with the help, you really saved our butts!

1 Like

Glad I could help! :slight_smile:

If you need anything else don’t hesitate to ask.

1 Like

Just thought I’d mention that I posted a bug report about this. It turns out, it’s not actually “UntrackedMemory”, per se, because Roblox does, in fact, track it. You’ll notice that once you hit 800MB, it stops increasing.

You might be asking why? Because that’s the threshold at which Roblox starts getting rid of collision data. It’s just that Roblox decided to store that collision data thinking you might use it later.

That being said, Roblox is going to be changing this threshold so that it longer stores collision data which it won’t really end up using, and will soon be categorizing it properly under “Physics” instead of “UntrackedMemory”.

All in all, it might not actually be good to store the parts/models/etc using the module that I made, because it probably just transfers this data to Physics, instead of leaving it under UntrackedMemory. But hey, who knows? It might actually be better than Roblox’s system… but I doubt it?

2 Likes

Well this method fixed the server crashing issues. I haven’t had a single one reported since making that change. There have been a few lag problems, but I believe they are unrelated and have to due with something else I did (or the extreme traffic Roblox is experiencing this month).

1 Like

So, in a nutshell, “Untracked” memory is from circular references. The key issue is that Roblox’s “connection list” of functions only informs Lua that a function is referenced, but not from where, leading to potential circular references that the garbage collector can’t identify or remove, resulting in memory leaks. Here’s some suggestions:

  1. Be Aware and Deliberate: Be conscious of the relationships between objects and functions. Always think about the lifecycle of your objects and how they reference each other.
  2. Use Weak Tables: Lua provides weak tables which allow the garbage collector to collect the keys and/or values of a table if they are only referenced in that table. You can use weak tables to store references that you don’t want to protect from garbage collection.
  3. Explicitly Break References: If you know that an object is no longer needed, you can explicitly set references to that object to nil. This will break any reference cycles and allow the garbage collector to clean up the object.
  4. Avoid Global Variables: Global variables can sometimes cause circular references because they can be accessed from anywhere in the program. Try to use local variables as much as possible.
  5. Watch Event Handlers: In the context of Roblox and other event-driven environments, be careful with event handlers that reference objects. Make sure to disconnect event handlers when they are no longer needed.
  6. Use Analyzing Tools: There are tools and plugins available that can help analyze your code for potential circular references or memory leaks. Regularly using these tools can help catch issues early.
2 Likes