- Home /
Can I see non-Monobehavior objects in the memory profiler?
Is there I way to see my non-monobehavior objects in the Memory Profiler? I can find all scripts that implements Monobehaviour but not my non-mb classes.
"$$anonymous$$anagedHeap.UsedSize" is the only place that is affected by these non-Unity objects - at least what I can see.
Is it by design that only Unity or derived classes can be reference traced with the memory profiler? Dear Unity, could it be possible to trace other objects as well, I'll give you a cookie if you can implement it :).
Have you looked up the Profiler class? It doesn't say it's bound to $$anonymous$$onoBehaviour derived classes only
Yes, I have looked up the Profiler class. I want to be able to see which objects are referencing others. I can do this for monobehaviour objects but I don't get the same info for non-mono objects.
Answer by Bunny83 · Feb 02, 2017 at 04:20 PM
No you can't. This information is only known to the GC. You should also keep in mind that the Memory you see for MonoBehaviour classes is mainly the native size. Unity is written in C++, not in C#. See the user manual about the Memory Profiler. Your "Non-MonoBehaviour classes" are simple .NET / Mono classes which are subject to garbage collection. MonoBehaviours are not. (well, maybe partly).
The GC tracks every bit and byte that is allocated on the managed heap. If an object is no longer referenced it will be garbage collected. This is also true for object chains, trees or rings. So if you have a variable to a class A, class A holds a reference to a class B instance and B references a class C instance. If you set your variable (that holds the A instance) to null or a different value the class is no longer accessable and will be garbage collected some time in the future. Along with A it will also collect B and C.
This object tracking is not accessable. It soley belongs to the GC. There are basically three ways why an object is still alive:
either it's referenced from some static / global variable.
it's referenced from a MonoBehaviour / ScriptableObject since those also persist.
or it's referenced from the current stack frame. So a reference that only "lives" inside the currently executing method.
Note that case 1 includes all UnityEngine.Object derived classes as those are the "native object" that Unity already tracks on the native code side.
Case 1 and 2 could be figured out by using reflection and iterate through all classes in all loaded assemblies. Check all classes for static fields and traverse all referenced classes the same way. Specifically for UnityEngine.Object derived classes (which includes MonoBehaviour and ScriptableObject) you can use Resources.FindObjectsOfTypeAll to get a list of all objects that are currently loaded.
Case 3 is basically impossible to determine from an outside perspective. Note that even coroutines do not really belong into this case (they are actually objects), it's also not possible to access them since the references to those classes are stored on the native side and you can't query them in any way. So it's possible to have an endless running coroutine that holds a huge tree of objects which aren't referenced somewhere else. Those can't be "detected" that way.
When you iterate through the object tree you have to be careful. First. since you have to store your results somewhere you should exclude your class from being traversed. Even more important is that you have to remember which object you have already checked. If you do not a circular reference would send your code into an infinite loop. Make sure you only traverse public and private fields and not properties. You may also run into problems with some built-in components and their private fields.
Though following those steps you can "manually" create a "snapshot" of all classes that are currently in memory and you have a chance to access them.
As you might have guessed I trying to find mem leaks that origin from dictionaries-inside-arrays-from-list-from-list-from-3rd-party-libs-from-references-from-dictionaries-from-static-variables. :/
If I understand you correct, I could write a tool that via reflection traverses all the references of objects dumps that to a log. Does anybody by chance already have such code implemented? Could save me a few hours if I could copy-paste it from somewhere :).
Well, it's possible that someone wrote already something like that. However it would be difficult to "search" for such a tool unless you already know one.
Though writing a tool that dumps all object trees stored in static references shouldn't be too complicated. The question is more about how you want to display that information. Dumping all references could result in a huge amount of data. You may want to filter that data in some way.
Your answer
Follow this Question
Related Questions
Object references listed in profiler but not in hierarchy. 1 Answer
Memory Leak Help 2 Answers
Performance going down over time 2 Answers
ManagedHeap.ReservedUnusedSize 0 Answers