Memory Leak - "Reserved" Going 10+ GB

We are having technical issues in editor, where the memory is always increasing after entering/exiting play mode.

I have been profiling and using the memory profiler, the managed space, specifically the “Reserved” section just keeps increasing, to the point where it reaches like 15GB of RAM. No other information is provided to us from Unity profiling.

Here is comparison of 2 snapshots after just one enter/exit play mode.

Any idea how to figure out what is wrong, what is increasing it? We are also calling
Resources.UnloadUnusedAssets();, but doesnt help.

Editor version? Be sure to try the latest patch release.

Is deep profiling possible with memory profiler?

2023.2.18, not sure upgrading more will help.
No, the deep profile does not seem to affect the memory snapshots.

Reserved involves Unity’s native memory management. I don’t think there’s anything you can actually do aside from change versions.

https://discussions.unity.com/t/902637/2

So then this seems to be a unity bug, as It just cannot grow to 30+ GB until I get out of memory.
Before it even reaches that, the editor is so slow its impossible to work with.

If it is the Reserved amount underneath the Native main table item in All If Memory, yes, but this one is the one in the Managed branch of the TreeView. That means this amount is controlled by the Boehm GC. (Also a native system for memory management, albeit not “Unity’s” and for the Boehm GC version used in Unity you can see the implementation for that by finding the Mono repo on our public GitHub, if you’re curious)

There is still limited control over it as reserved space would require the Boehm GC to unmap and return previously used memory address ranges it allocated to the system, which it doesn’t (on almost all platforms). I.e. it will unmap it and immediately remap it for later use, though that would currently end up as untracked memory, and is likely to become non resident over time (unless reused) as the OS realizes your app isn’t using that memory.

Before that happens and while it is still counted as reserved as in your case, it might still be counted as non resident. Since you’re on 2023.2, you could update to version 1.1.0 of the package and switch the table mode to show you how much of that is resident.

And you could take a capture before exiting Playmode and compare the 2 to draw conclusions on what managed memory usage might have inflated the managed heap in this way. Also if this growth keeps happening, you might be fragmenting the heap to bits. As for who’s at fault for that, your code, Unity’s Code or a mix of both is impossible to tell without a deeper analysis.

Oh and version 1.0 might have missed managed objects exclusively held in memory by static variables of struct types. If, by pure chance, 1.1 takes forever to open your snapshot, you likely have some ginourmous managed arrays held this way. I’m on a fix for that one.

1 Like

Yeah we are already on 1.1 of memory profiler package, and yes, the snapshots takes several minutes to open, sometimes 10 seconds :slight_smile:

I have already submitted bug report under case 74596.

Also what is the difference between reserved allocated and resident? Would it help to pinpoint the issue? As I was expecting I could see maybe some variable name of code where the memory is kept so much, maybe some static variable that is leaking, no idea, maybe I expected this to be too easy.

Ah, your first screenshots were from version 1.0 so I thought I’d mention 1.1.

The difference between resident vs allocated is that you can allocate more than what is physically free for your app to use, as it only maps to physical memory once it becomes resident. I.e. memory in your page file on windows is non-resident. You can check this blog post for details.

For memory that is still in use that’s the case. Reserved memory is more difficult to analyze and can only be reasoned about based on what was in there while it was still referenced and not yet GCed/freed. I.e. that takes a bit more inference and comparing snapshots and checking what’s getting removed between snapshots (though there could also always be allocations that happen between snapshots).