What on earth is "Reserved" memory and why is killing me?

Hey there, we’ve got a brutal memory problem I’m trying to track down.

Observe the following screen shot:

We start in the main menu, head in game, and then return to the main menu. in that process there is ~800MB that weren’t there before. also, as you can see, the vast majority of this shows up as “Reserved” whatever that means and does not show up in the Tree view or Memory Breakdown, which makes it basically impossible to debug.

Is there any way to make sense of this??

2 Likes

Hi @hypnoslave !

“Reserved” highlights the memory that was allocated from the operating system for Unity’s native memory management system.

Unity memory management uses pooling system for native allocations. We allocate a relatively large sequence of pages of 4-32MB in total size and then serve smaller allocations for different subsystems (e.g. Unity objects).
The “reserved” part itself is the difference between total pool size and what is actually used by Unity’s native memory manager.

We are planning to add more insights in the All of Memory view to the Reserved node in the next Memory Profiler release, however we do also have reservations as this may be not really actionable and hidden by default. (There could be a possibility of using Unity - Manual: Customize allocators to play with the “reserved” overhead, although it is a game of memory vs performance overhead).

Hope that clarifies what reserved part means.

1 Like

interesting, thank you very much for taking the time to reply.

It appeared that we were running into an out of memory crash on… a platform we were developing for… but it didn’t appear that the “used” portion was capping out. However I might have been confused.

What if Unity has amassed a large amount of reserved memory that it’s not using, but even so, tries to reserve more, but can’t? Can that theoretically lead to a crash?

That would be a serious bug!

If that did happen, it wouldn’t necessarily cause a crash: it’s not like it needed that memory yet. However, once you start bumping into failure to allocate memory, your program is probably about to die anyway – something else will need to allocate memory, and it will not be negotiable :stuck_out_tongue:

1 Like

Yes, it is possible - this problem is known as “memory fragmentation”. The allocation and deallocation pattern may result in larger blocks being underutilized and ever growing. It is relevant to both native and managed memory managers.
Although it maybe relatively hard to crash on platforms where memory is paged, but it will definitely impact performance to some extent.

oOOoooh of course! memory fragmentation. it says it has the space reserved, it doesn’t say it’s all reserved together.

is there anything I can do on the C# side to … i dunno. defrag? somehow?

It’s not just fragmentation. If you take a snapshot while you’re in game for the first time it probably shows most of that as used. If it reuses most of the space when you go back for a second time after going to the menu, fragmentation isn’t your issue either. It is that the in game scene pushed your high water mark up and Unity’s allocators are generally greedy because asking for memory is costly, so they will keep the memory reserved, assuming it will likely be reused.

It can also be that the high water mark is reached at the point of loading a scene, as the memory used for assets used in the previous scene is not unloaded as that scene is unloaded but only on the next unload after that, in case it would be reused in the next scene. Loading an empty scene in-between or calling Resources.UnloadUnusedAssets is a possible way to trade of longer loading times for lower high water marks of memory usage.

5 Likes

that is fascinating. what an interesting idea … loading an empty scene.

Thanks Martin, I’ll do some tests…

Hello @hypnoslave !
I am facing the same issue described in your OP. I have tried using an empty scene between loads but it did not change much. Did you ever resolve or understand what was going on in the end?

It’s probably worth mentioning that this happens when I load and unload a video from an AssetBundle. I use LoadFromMemory with an Uncompressed Asset Bundle.

sorry @mylastggeast , I solved my memory management issues using old-school techniques of crunching down content until I was no longer encountering console crashes. That’s it, I’m afraid. I wish I could say I’ve come out the other side of this process with wisdom, but… :slight_smile: newp.

2 Likes

Thanks for the update!
On my end, after some investigation, I came to the conclusion that Unity allocates more stuff when it detects newly used classes (eg when I open the video player for the first time?) and reserves memory because of that, but watching the videos over and over has no effect over memory so no leak involved.
I hope I am right, time will tell!

1 Like

Give an example of C memory allocation. When you use the malloc function, it doesn’t actually allocate actual physical memory, it just allocates memory in virtual space. Only after you write to this memory, such as memset operation, the physical memory will be mapped. Something like the code below

int size = 1024*8;
char* sz = (char*)malloc(size);
memset(sz, 0, size);

After memset, 8k of physical memory is allocated. Of course, memset is just an example, and any write operation will cause it to allocate physical memory.
For another example, memset(sz, 0, size/2); At this time, only 4k of physical memory is allocated. The remaining 4k is the reserved part.

2 Likes

[mention|UAsuCsT71d3FF/W/xJ0QWQ==] yes, resident vs allocated memory is another topic related to the question of Reserved memory in so far as that the reserve memory doesn’t necessarily have to be resident. In the 1.1.0-exp.1 version of the Memory Profiler we’ve added the ability to analyze that difference more granularly, and we just released a blog post that goes into more detail on the topic.

That blog post also provides some tips about analyzing Reserved memory, like

2 Likes

Hello, the “1.1.0-exp.1 version of the Memory Profiler” link can not be found, any update? Thank you!

Whoops, looks like I pasted the link in there twice and thereby broke it. I’ve corrected it in the post itself.

But also, since then, we released version 1.1.0-pre.1 . For details on the latest version, you can always check the pinned threads in the Profiler Previews subforum and we do try our best to remember to update this thread as close to the release date as possible, so you can switch on “Watch this thread” for notifications of new version releases.

Do note that the blog post mentioned above still has a mistake in it in claiming that the more granular per object breakdown of allocated vs resident would be available for captures taken of 2022.2+ versions, that is only available for captures from 2023.1+ versions.

1 Like

@MartinTilo is memory ever given back to the system? For example if we have a lot during a scene load, but then after the scene loads, the used memory usage goes down. Is this previously reserved memory given back to the OS? Or does Unity keep it allocated for the duration of the game session?

We have in some cases extremely high reserved values (greater than 250 MB) which on mobile is a massive amount. So we want to know what we can do to improve this.

It depends. Managed memory may be returned to the OS once a page (usually about 4kb) has been entirely empty for a while (every 6th GC.Collect in the current implementation of the Mono and IL2CPP Boehm GC as of writing. This is an implementation detail that you shouldn’t bank on. Also, calling GC.Collect multiple times until you hit that GC_CollectsSinceStartup % 6 == 0 is not helpful and should be avoided. That is, because it will fragment longer contiguous virtual address space that could have been reused even further.)

Native memory may, depending on the Allocator, also be unloaded but that may be even less predictable to the point where you might as well assume it won’t happen.

That said, different platforms deal with stale memory differently. Such unused memory may end up getting pushed out of Resident memory by getting compressed, moved to swap file/ just unmapped from physical memory until needed again.

You can go into the Memory Profiler preferences and check the option to see detailed breakdowns for reserved memory. With 2023.1+ and package version 1.1 you can also get per page granularity residency information displayed that may help you identify what of that you actually need to care about, i.e. allocated but non-resident unused reserved memory won’t get your app evicted by the OS.

1 Like

Hi I have a similar issue with unity 2022.3.3, when I loading the same scene I have a memory leak of reserved (Unused) memory

there is any way to fix it? have sense to upgrade the project to a newer version of unity?
I already tried to use:

System.GC.Collect();
Resources.UnloadUnusedAssets();

But this not fix the problem…
Please help

That makes no sense. A memory leak would mean that something would stick around that shouldn’t but reserved space is literally empty space. You can reuse that with later usage but you can’t leak that.

You can fragment it or bloat it up with a high water-water-mark though. Using version 1.1 of the package and by enabling it in the preferences you can see how much is reserved on a per allocator basis and then maybe improve on fragmentation via allocator customization. For the high water mark, you can load to an empty scene between scene loads to give the assets from the previous scene an extra scene load jump to unload (they unload with one scene load delay in case they’d be reused by the next scene).