Search Unity

What does all of this mean? Trying to track a memory leak

Discussion in 'Editor & General Support' started by malkere, Oct 25, 2020.

  1. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    For three days now I've been taking snapshots, trial and error'ing systems in my game on and off, and I still can't seem to find what is causing my memory leaks.

    I'm keeping references and explicitly Destroy()'ing all my Texture2Ds and Meshes created in runtime, setting to null my larger dictionaries and lists of data that get generated and used in runtime, and never calling Resources.Load() on anything more than once. This also did not used to be a problem. I made a lot of changes over the past few months increasing my performance a lot, but now I've noticed this leak and can't track it down.

    Every time I teleport to a new area (infinite procedural world) the memory usage goes up ~200MB. I can load a save, return to the main menu, and the memory usage has gone up 200MB. And I can get it up to 10GB by repeating this. At which point the profiler's memory section still only shows 3.6GB of textures, and several hundred MB of other things. Which I assume means we're dealing with native memory leaks, as it's not spotting it as managed objects.

    After many hours of no luck with the memory profiler, I created a FindObjectsOfType<> method to gather counts on objects it could find in memory, and it does show a steady increase in objects despite returning to the main menu.

    A memory snapshot from the memory profiler shows a lot of native objects than I don't understand:
    upload_2020-10-25_21-59-58.png

    the size looks huge on something up there. Can anyone understand what that is? How I can look further into this? Any insight on where/how to look would be most appreciated.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    Something that large is most likely textures. It might be in-engine and beyond your control, but I wouldn't assume that until you can prove it.

    I recommend trivially changing one section of your project at a time to use a ridiculously small version of the textures it loads and Instantiates, such as using the Unity importer to make a bunch of textures tiny, like cap them at 64x64, then re-run your experiment.

    I predict when you find the texture that is leaking, the leak will suddenly get much smaller, and then you can reason about all the ways that offending texture might be causing problems.

    Note: I presume you are using source control and can easily revert all such experimental changes. If not, install source control now. Unity and git are an unbeatable combo.
     
  3. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    Frustrated and "trying to fall asleep" last night I realized the biggest change I made to my system was actually generating the Terrains and TerrainDatas on my own... I just tested Destroy()ing them explicitly and the memory is piling up a lot less now. Definitely not 100% of what I need to fix but a large chunk of it...

    I'm curious if... all, my custom classes are going to be needing explicit destruction?? That is, anything marked [Serializable] ?
     
  4. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    So I setup a little test that just spams a new [Serializable] MemoryTestObject class every frame without ever calling Destroy() and the GC is properly collecting it. So I'm not personally clear on what constitutes things that can remain as native objects in memory despite destruction of for example all objects in scene, and of course no references on ScriptableObjects or static objects.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    Not sure what needs explicit destruction... I know that stuff no longer referenced is generally cleared when changing scenes (or calling UnloadUnusedAssets) and there is no reference to it, but yeah, explicit destruction lets you reclaim in the same scene.
     
  6. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    Ya, I just need a list or clear explanation of what is by default generating native allocations... Unity memory management guide says:

    Still not clear what defines an "Asset" or an "Object" in this explanation though... as clearly normal primitives and classes and what not get properly GC'd...
     
  7. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    So I load into my level, then load into an empty scene and do this:

    Code (CSharp):
    1.     void CountType<T>() {
    2.         Object[] objects = FindObjectsOfType(typeof(T));
    3.         Debug.Log(typeof(T).ToString() + " found: " + objects.Length);
    4.         for (int i = 0; i < objects.Length; i++) {
    5.             Debug.Log(typeof(T).ToString() + " name: " + objects[i].name + ". Of type: " + objects[i].GetType());
    6.         }
    7.     }
    8.  
    Initially I was checking Texture2D, etc., just for a total count, but I called it using Object, and had it print out the GetType() for all of them, so it's clear what shouldn't still be there.

    And it looks like I still have a bunch of unaccounted for Sprites. If the memory profiler could have just shown me that somehow in the first place I could have gone into my code from there =o= Should be able to identify my problems and fix them now.
     
  8. JoNax97

    JoNax97

    Joined:
    Feb 4, 2016
    Posts:
    611
    That would be anything that has a C++ counterpart, so as a rule of thumb, anything derived from UnityEngine.Object
     
    malkere and Kurt-Dekker like this.