- Home /
Mono heap size problem (debugging is hard, no SGen)
Hey all,
For a project at the University, I'm working with a team on a Unity game with high RAM usage. An external company has delivered us a lot of 3D data from the real world. This is data like the data in Google Streetview (as 3D triangle meshes + textures). This data is about ~100MB per 50x50m block, but could increase to ~200-300MB per block.
Seeing how this data is so large, we stream this data via a server. If the player leaves the neighbourhood, the block will be destroyed.
Here comes our problem: Mono keeps the giant heap (which can grow to 6GB) reserved, and does not defragment/compact the heap. The Unity profiler only shows us Unity RAM, which is not really a problem. The Mono RAM however, is not accessible in Unity.
We have multiple questions:
Does anyone know if we can see/profile our Mono RAM somewhere?
Seeing how Unity 5.2.0 uses Mono 2.0, an old garbage collector is used (sadly no SGen). Is there some way to use it or optimize our memory in another way?
If I didn't provide enough info for you guys to answer our questions, I'm sorry! Feel free to ask more!
Thanks in advance.
Luuk-
Same for us too. We managed to get the heap size under control by manually calling GC.Collect(), but this is far from ideal. We need a way to debug the heap, like CLRProfiler for .Net.
I've posted an answer. A lot people seem to think that Unity is a managed application, but it's not. Unity is mainly written in C++ and Unity does it's own memory management of the native resources. On top of that you have $$anonymous$$ono as scripting environment. $$anonymous$$ono has it's own heap / heap area within the native application.
Thanks for the update, and detailed answer below. It might even be the root of our problem.
Answer by Bunny83 · Dec 14, 2015 at 08:09 AM
Well, i guess you might have forgotten to actually destroy the mesh object unless you actually reuse it. Keep in mind that using the .mesh
property will create a duplicate of the original mesh. The same thing happens with .material
. If you want to completely destroy an object you have to destroy the mesh and material as well.
Also keep in mind that a lot built-in Unity classes are actually "managed proxy classes" for C++ objects. For example:
void FooBar()
{
Mesh m = new Mesh();
}
calling "FooBar" will create a new Mesh object. The local variable m seems to be the only managed reference to that object and when FooBar finishes you might think that the mesh is up for garbage collection. However that's not the case. Every class that is derived from UnityEngine.Object is a "tracked" object that has a native counterpart in the C++ world. See the class tree for a complete list (just find the "Object" class and see all the derived classes). Even you lost all references to an object you can simply ask Unity for the reference by using FindObjectsOfType. This method can find any UnityEngine.Object derived instance. Likewise all those objects can and have to be destroyed using the Destroy method.
When you call Resources.UnloadUnusedAssets, Unity will destroy all objects which aren't currently in use. Our mesh object would be destroyed as well. UnloadUnusedAssets is implicitly called when you load a new scene. So objects that might have created materials, meshes, audioclips, textures, shaders, ... usually don't have to worry about cleaning up those objects when a scene change happens. However if you constantly creating new objects without cleaning up the hidden siblings, you just created a memory leak.
Thanks, this is a great answer and advances my understanding of the internals of Unity. So calling the Destroy() method is akin to the .Net Dispose()? In our case something is chewing up native resources and calling GC.Collect() releases them. This implies that when the the GC gets to the offending managed object, it is either doing Dispose or Destroy, but since we've been careful with managed allocations, the GC doesn't kick in automatically.
So my question is, if we don't load a new scene or call UnloadUnusedAssets, must we explicitly call Destroy or could the GC be destroying those UnityEngine.Object instances for us?
Sorry, one more question without notice :)
You said setting .mesh creates a copy, so setting .shared$$anonymous$$esh avoids that right?
Your answer
![](https://koobas.hobune.stream/wayback/20220612041415im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
,Can I get runtime data of unity without needing source code? 0 Answers
What is `assets/bin/Data/Managed/etc/mono/xxx` contain ? 0 Answers
mono.security.dll is denied? 1 Answer
Out of memory error 0 Answers