Search Unity

Large memory cannot be reclaimed

Discussion in 'Editor & General Support' started by NeverMore_, Jan 14, 2022.

  1. NeverMore_

    NeverMore_

    Joined:
    Apr 16, 2021
    Posts:
    7
    We have a large json file and after multiple deserialization there is a memory leak. I began to suspect that it was a problem with the json library(newtonsoft.json,litjson,utf8json), but it still appeared after replacing a few. So I guess whether it may be caused by too large allocated memory. Through the following code, there is indeed a situation where the memory cannot be released. Why does this happen and how to fix it. Of course, native memory can be allocated through C++, but the cost is too high. I hope the official can give some suggestions and explain the principle.

    unity2020.2.6f1
    The editor is normal, there will be problems after packaging the exe


    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4. public class GCTest : MonoBehaviour
    5. {
    6.     const int DefaultSize = 300;
    7.  
    8.     int MemorySize = DefaultSize;
    9.     // Start is called before the first frame update
    10.     void Start()
    11.     {
    12.         var strs = Environment.GetCommandLineArgs();
    13.         if (strs.Length == 2)
    14.         {
    15.             if (!int.TryParse(strs[1], out MemorySize))
    16.                 MemorySize = DefaultSize;
    17.         }
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.         if (Input.GetKeyDown(KeyCode.Space))
    24.         {
    25.             var bytes = new byte[1024 * 1024 * MemorySize];
    26.         }
    27.  
    28.         if (Input.GetKeyDown(KeyCode.KeypadEnter))
    29.         {
    30.             Debug.LogError("Gc");
    31.             GC.Collect();
    32.         }
    33.     }
    34. }
    35.  
     
  2. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    The object will be collected but the Managed Heap will keep it's expanded state for a moment longer, keeping the allocated space ready to be reused by new objects if needed. If this space isn't reused, it will be released to the OS again during a subsequent GC.Collect(). When exactly is an implementation detail you shouldn't rely on but at the moment, every 6th GC.Collect cycle should release such memory. You can also investigate this with the Memory Profiler. The empty managed space should show up in the bar diagrams and on the Fragmentation page.
     
  3. NeverMore_

    NeverMore_

    Joined:
    Apr 16, 2021
    Posts:
    7
    When I did the test, GC.Collect() was called far more than six times, but the memory could not fall. And when I allocate 300m again, the memory will go up. I checked through the Memory Profiler, and there are indeed several 300m pieces of memory, and I can't find a reference to it. So how should I solve it in this case, because our json data is created by the user, I can't control its size, so it is easy to generate large memory allocation during deserialization.
     

    Attached Files: