Hello, I am trying to implement a system to handle asset loading and I am using addressables. Everything worked perfectly, it loads and unloads scenes without freezing the main thread, which allows me to play some cool animation while the player waits. Until I started profiling the memory usage.
In my project I have two scenes:
Scene 1 behaviour:
Loading: memory usage increases by 10~15mb.
Unloading: no noticeable changes on memory usage.
Repeat: memory usage increases by around 2~5mb every time scene loads again.
Scene 2 behaviour:
Loading: memory usage increases by 100~150mb.
Unloading: memory usage decreasing by seemingly the same amount it increased when loaded.
Repeat: memory usage seems to go back exactly as before most of times, unless if I load\unload too quickly, then I get the usual 2~5mb memory increase.
Repeating the above process for any of the scenes keeps increasing memory usage by 2~5mb everytime the scene loads again.
Where I tested:
1 - Windows
2 - Android (Meta Quest 2)
Where I monitored memory:
1 - Windows task manager
2 - Oculus OVR metrics tool
@arielcorrea , Hi there, if at all possible I recommend you use the Addressables memory profiler module as a way to get the most accurate representation of what Addressable assets or scenes are loaded at runtime - this should help you fix any issues with things potentially not being unloaded. If memory continues to increase and the profiler reads that there are no increases, then that may speak to a bug in Addressables, in which case if you could submit a bug report reproducing the issue we should be able to take a look at it.
As far as the issue itself, my usual recommendation when someone unloads something and nothing seems to happen to the memory, its usually due to the (somewhat strange) way that assetbundles function. This behavior is detailed in this docs page, but the gist is that when you load something from an assetbundle, it won’t be cleared from memory until everything in the assetbundle is unloaded. This means that if you load two assets from an assetbundle, and then only unload one, the memory usage will stay the same until you unload the second asset, at which point the whole assetbundle will be unloaded and the memory will be cleared. I hope this helps!
@unity_shane , Hello! Thank you for taking the time to answer! I couldn’t manage to enable the Addressables memory profiler module. I installed the profiling package and everything, but it simply doesn’t show as an option on the profiler. So I used the Addressables Event Viewer instead. I built a debug version for Windows, ran it and it seem to show proper ref counts for the addressables reference.
Ref count at 0 (if I read correctly), memory goes back down, but there is some additional 40mb from what it was before loading the scene.
I ran the analyzer before testing and it found some Unity standard shaders being referenced on all scenes, these were moved into their own bundle, at least for duplicates I should be good I suppose Let me know if there is anything else I could do. If you think it is necessary I can try a different unity version to see if I can make the Addressables profiler module work.
Just wanted to mention, that i ran into the same problem. Ram keeps increasing when loading and unloading the same addressable scene. I went from an inital 600mb to 2000mb just by repeating these steps. And it didnt stop there.
Addressables unloading does not free the memory it only reduces the ref count. Resources.UnloadUnusedAssets() will free everything with ref count 0 but it causes some fps drop, I guess because it has to check everything instead of just the one asset you are working with.
Bad design in my opinion.
Hello @Nilokilo , Like unity_shane said and is stated on the docs, it keeps an asset bundle in memory if there is anything referencing any of the assets inside it. So I expected it to clear memory once I remove all references, which is what I am doing. If what you are saying is true, that would explain it. Could you tell me how you found this?
Hello @Wilhelm_LikeAStar and @JWittig , I haven’t had the time to test again, right now it is not a deal breaker for me, I needed to follow through implementing my system. I recently updated to Unity 2022 where I am planning to do some testing again with the newest version of addressables. In my case it seemed to kind of stabilize at some point and like I showed, the memory load did decrease after the addressables unload call, just not completely.
I found this because the app I’m working on crashes due to out of memory. What I was doing is loading several textures (~60) and pack them into an atlas at runtime and then release the references again. I thought that’s enough but inspecting the memory usage I saw it went up every time until it crashed. Looking at the documentation I found this function and this did the trick, the memory was cleaned up properly.
The cheaper way is likely to take a (or multiple) memory snapshot(s) with the Memory Profiler package (I recommend the latest version, currently 1.1.0-pre.1) and digging for whichever Texture’s you have lying around that are effectively unused and therefore have a status of Leaked Dynamically Runtime Created Asset in there selection details panel in the Memory Profiler.
Identify that, maybe by ensuring you give all your created Textures a name (through their .name property) and once identified, make sure you call Destroy(tex) on them. That’s way lower overhead than Resources.UnloadUnusedAssets, given that it’s way more precise.
First it’d be good to check that this is actually caused by Addressables and not by creating a new Texture at runtime hence my suggestion to take memory snapshots and investigate those to be sure.
If instances of types inheriting from UnityEngine.Object, that are not GameObjects/Components(including MonoBehaviours), are created at runtime from C# code, it’s the responsibility of the creating C# code to clean them up when they are no longer needed (these, in this case Asset Type, UnityObjects are backed by NativeResources. Asset Type Runtime Created objects are not tied to a scene that would unload and drag them along when that happens, they will just stay there until aResources.UnloadUnusedAssets or Destroy call frees them up again. Think of it like an IDisposable DataStream, just instead of Dispose() you call Destroy ()) . I don’t have enough visibility or understanding of what exactly you’re doing here so I can’t make a determination on whether that is Addressables C# code or yours.
Hi there.
Do addressables actually unload an asset from memory when the refCount is zero? Or do they not?
If they don’t - will calling Destroy on that asset manually - free up the memory?
Please give us a straight answer my good sir.
I actually have my own wrapper around Addressables, and adding this Destroy call would be an easy task, I just automatically assumed that calling Addressables.Release would free up memory when refCount reaches zero… I mean, its supposed to be the whole point of the system, right?
I’m afraid I’m not the expert on this system that you’re looking for (my turf is more on the (Memory) Profiler, so, if in doubt, like here, I’d just recommend you to use that to see what it can tell you ). I’m vaguely aware of some bugs in that space that led to a slight change in the documentation to make the expected behavior clearer in there but I’d recommend to check the documentation for the version of the package that applies to your project.