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/ Quote from https://docs.unity3d.com/Manual/webgl-memory.html 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/ : I tried this tactic in test project using GC.Collect() instead of unloading scenes. Test1: Code (CSharp): var buf = new byte[1700 * 1024 * 1024]; buff = null; GC.Collect(); log(Profiler.GetMonoUsedSizeLong()); ---- result GetMonoUsedSizeLong > 1700mb Test2: Code (CSharp): var buf = new List<byte[]>{new byte[10 * 1024 * 1024], ..., new byte[10 * 1024 * 1024]}; //size >1900mb buff = null; GC.Collect(); log(Profiler.GetMonoUsedSizeLong()); ---- result GetMonoUsedSizeLong == 10mb Test3: Code (CSharp): 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 buff = null; GC.Collect(); log(Profiler.GetMonoUsedSizeLong()); ---- 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 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?
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.
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?
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.