Memory Profiler: Large gap between Unity Objects and Total Resident Memory

Hello everyone,

I’m currently trying to optimize the RAM usage of my game, but I’m running into some confusion.

When I capture memory using the Memory Profiler on a real device (with a build of my game), I see multiple memory values. From my understanding, I can mainly impact the Unity Objects memory.

At the moment:

  • Unity Objects: ~509 MB
  • Total Resident Memory on device: ~1.44 GB

This leaves almost 1 GB of memory that doesn’t seem to be part of Unity Objects.

So my questions are:

  • Is this expected?
  • Is that ~1 GB something I cannot directly control?
  • Or is there a way to debug and optimize that part as well?

I feel like I might be misunderstanding how memory is reported here, so any clarification would be greatly appreciated.

Thanks in advance for your help!


Depends on how you define “part of”. I.e. your MonoBehaviour and ScriptableObject types could be holding on to managed objects (directly and as a a chain of objects), which are not counted towards the size of Unity Objects in this table. There’s also managed memory that’s held onto by static fields.

Beyond managed memory, the Unity Object and features you use in your game have an impact on the memory used for the native subsystems and managers behind them, e.g. every object contributes to the size of BaseObjectManager (mapping InstanceId/EntityId to pointer and native type to object lists) and every persistent file has it’s InstanceId mapped to the file id in the PersistentManager.Remapper.

Then there is also UnsafeUtility, aka the native memory behind NativeArray and other native collections, which either your scripts or features you’re using could be allocating directly from C#.

You can also save memory by disabling Unity modules you’re not using.

Native Plugins may be allocating native memory (which may be under Untracked if they don’t use our Native Plugins API to allocate via our Memory Manager).

Etc.

So it’s wrong to assume you can only directly impact the memory on the Unity Objects table directly. It’s the easiest to assess and reason about for most users as it’s closely tied to the assets and scenes they work with in the Editor every day, which is why I’m currently working on making the incidental memory impact of these easier to assess (see the Impact numbers in the selection details in the latest versions of the Memory Profiler package for a glimpse of that), but it’s not the only thing you have control over.

It’s hard to be more specific what could be the case for your project here without seeing more details though.

Hi! Thanks for your reply!

Could you point out some of the details to look out that could impact the 1Gb of memory? or point out a tutorial/doc? I use a lots of unity services, and some external sdk (Facebook, LevelPlay, AppsFlyer …), but I don’t know the ram impact of each ones :confused:

Here are my assembly references, if you notice anything suspicious.

Yes, albeit my immediate observation (friendly wording for :exploding_head:) is not memory related. :wink:

Given the number of dependencies, I’d say this is your project’s one and only Assembly Definition. If that is the case, you might as well remove it entirely since you aren’t using Assembly Definitions for what they were designed for: to decouple your code from a large (and ever-growing) number of dependencies.

As to memory usage, a little bit can sometimes go long ways:

  • Remove any packages (and assets) from Package Manager that you do not actually use.
  • Player settings: enable Managed Code Stripping and make builds with an increasingly higher stripping level. It may break the game eventually, in that case settle back to a lower setting OR spend some time and figure out what type(s) are causing problems and exclude them from stripping.

The memory gains from these steps are likely relatively low (eg < 50 MB) but could overall reap some benefits nevertheless for just a few steps. Stripping takes some time during build but can be offset by faster IL2CPP builds. It can also shave off a couple MB from your build size.

For profiling, also look into Android Studio Profiler since it’ll provide with more low-level details.

One thing to verify: does your app’s memory usage grow during repeat life-cycles? Eg enter play, exit to menu, enter play, etc … or just progressing through levels. Steps that a player might do several times per session which involve scene or resource loading. You’ll want to ensure you aren’t leaking notable amounts of memory.

The top-3 items Textures, Shaders, and Meshes make up for almost 400 MB of memory, but as expected account for the Pareto-typical 80% of the Unity Objects category. So I’d say - if there is an issue at all - it’s likely found in services, SDKs, or leaked memory. But keep in mind that this “extra 1 GB” is also Unity engine memory usage, including GPU memory for frame buffers and such.

What does the All of Memory tab show? The Unknown/Subsystems usage listed in there is what you cannot influence, or only very indirectly. You could sum that up, deduct it from the 1.44 GB, deduct the 500 MB you can directly assess, and then consider if that part of memory is worth further analysis or not (eg probably not if it’s < 250 MB and you haven’t even explored texture optimizations eg compression, max size reduction, color bit depth reduction).

To add to what @CodeSmile wrote, also check the modules in the package manager, as that’s what I meant with disabling Unity modules. The SDKs are likely to contribute towards Untracked memory usage so unless their developers start using the plugin API, using a platform native Profiler like Android studio is the only way to get a better idea of their memory impact.

Also with lacking more details I mostly meant the All Off Memory table.