Search Unity

GC.Collect in WebGL

Discussion in 'Web' started by MamXam, Mar 30, 2020.

  1. MamXam

    MamXam

    Joined:
    May 9, 2018
    Posts:
    2
    Hello, I have some questions about GC's work, could you please explain:
    Quote from https://blogs.unity3d.com/2016/12/05/unity-webgl-memory-the-unity-heap/
    Скриншот 30-03-2020 133229.jpg
    Quote from https://docs.unity3d.com/Manual/webgl-memory.html
    Скриншот 30-03-2020 133409.jpg
    It seems that there's a contradiction. So what's the right variant:
    1. GC.Collect() call actually works, but only between frames, and clears not everything (without loading/unloading scenes)
    2. GC.Collect() call doesn't work at all. Unity on its own makes some small cleanup after every frame, not GC.Collect().


    Quote from https://blogs.unity3d.com/2016/12/05/unity-webgl-memory-the-unity-heap/ :
    Скриншот 30-03-2020 133532.jpg
    I tried this tactic in test project using GC.Collect() instead of unloading scenes.
    Test1:
    Code (CSharp):
    1. var buf = new byte[1700 * 1024 * 1024];
    2. buff = null;
    3. GC.Collect();
    4. log(Profiler.GetMonoUsedSizeLong());
    5. ----
    6. result GetMonoUsedSizeLong > 1700mb
    Test2:
    Code (CSharp):
    1. var buf = new List<byte[]>{new byte[10 * 1024 * 1024], ..., new byte[10 * 1024 * 1024]}; //size >1900mb
    2. buff = null;
    3. GC.Collect();
    4. log(Profiler.GetMonoUsedSizeLong());
    5. ----
    6. result GetMonoUsedSizeLong == 10mb
    Test3:
    Code (CSharp):
    1. var buf = new List<byte[]>{new byte[400 * 1024 * 1024], new byte[400 * 1024 * 1024], new byte[400 * 1024 * 1024], new byte[400 * 1024 * 1024], new byte[400 * 1024 * 1024]}; //size 2000mb
    2. buff = null;
    3. GC.Collect();
    4. log(Profiler.GetMonoUsedSizeLong());
    5. ----
    6. result GetMonoUsedSizeLong == 400mb
    So, the question is: does GC.Collect() work at all? If it does, why sometimes it cleans memory, sometimes not. The example is very simple, there's nothing to fragment in memory.


    And another question about generations.
    Quote from https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity4-1.html
    Скриншот 30-03-2020 133711.jpg
    Does it mean that everything, described here https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/large-object-heap about generations is wrong for the unity engine?
     
  2. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    That documentation is pretty ancient by now. We didn't have wasm (stable) in 2016, and we didn't have dynamic memory growth back then either. We have both now, and while I'm not sure if GC.Collect() has been updated since then, I'm sure it has. The Unity WebGL team has been very lackluster with their documentation and forum responses, I'm guessing they're busy working on the next big web platform project (WebGPU?).

    As to your last question, Microsoft's CLR (common language runtime) runs a much newer garbage collector that is generational and compacting. When Unity compiles your C# code to C++ via IL2CPP, it uses the older, simpler garbage collector, and that's what they're talking about. Since 2016 we have gotten a new Roslyn compiler, which has allowed Unity to update the runtime to .Net 4.X equivalent (was .Net 3.5). However, they still use IL2CPP to compile for WebGL, and I don't think they will be upgrading the garbage collector for that any time soon.

    They really do need to update those docs, though.
     
    sukumarBabu and MamXam like this.
  3. MamXam

    MamXam

    Joined:
    May 9, 2018
    Posts:
    2
    I want to get the exact answer from the unity team. I don’t know where to look for the answer and what document to believe.
    I tried to conduct tests with loading/unloading of scenes, but the memory is not cleaned.
    Why?
     
    sukumarBabu likes this.
  4. sukumarBabu

    sukumarBabu

    Joined:
    Mar 23, 2015
    Posts:
    2
    Any update on this guys, i am also facing the same issue..

    "Out of memory in WebGL build"

    Console Log :
    Cannot enlarge memory arrays. Either
    (1) compile with -s TOTAL_MEMORY=X with X higher than the current value 268435456,
    (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations,
    (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0


    If i try to increase the TOTAL_MEMORY in the .json file. I don't even know whether it actually increases are not.