Why are some roots not identified?

Use this forum for questions on how to use .NET Memory Profiler and how to analyse memory usage.
Post Reply
mgweeks
Posts: 1
Joined: Wed Mar 09, 2005 9:41 pm

Why are some roots not identified?

Post by mgweeks » Wed Mar 09, 2005 9:51 pm

Firstly, I'm very impressed with this software. I've been trying to solve memory leaks an application and managed to close a couple of loopholes that had cropped up. I've got one last one that is causing objects to stay in memory and the root path only shows up if I unselect "Only include identified roots". I think the documentation is unclear about exactly what unidentified roots are. What are they if not one of the identified types?

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Post by Andreas Suurkuusk » Wed Mar 09, 2005 10:17 pm

Hi,

Even though we try to identify the roots of an instance, there are some roots which we cannot identify. Examples are:
  • Internal roots of the runtime
    The runtime keeps references to a bunch of instances,
    e.g. application domains objects, Runtime types etc.
  • Weak references
    Instances that are wrapped in a GC handle using GCHandle.Alloc
  • Thread static variables
    The current version does not evaluate variables for each thread.
  • The finalization queue
    Instances in the finalization queue will also have an unidentified <root>
  • COM wrappers
    Instances that are wrapped in a CCW will be referenced by <root> as long as the reference count is > 0.
It may also be possible that we fail to evaluate some local variables or arguments, depending on the state of the program when a snapshot is collected.

Best regards,

Andreas Suurkuusk
SciTech Software AB

clintmiller

Re: Why are some roots not identified?

Post by clintmiller » Wed Jan 18, 2006 11:07 pm

I'm in complete agreement with mgweeks, but I'm in a situation where I have an object that I dispose correctly, Memory Profiler tells me has been disposed, yet has an one unidentified root. The object in question isn't an internal CLR structure, a thread static variable, on the finalization queue (freachable list)--it doesn't even have a finalizer, nor is it wrapped by a CCW.

I even disabled the part of my application that loads assemblies in separate application domains and then unloads them. There was a note in the Memory Profiler documentation about root referee identification being broken in the case where assemblies are unloaded (only possible in other application domains) due to a bug in the framework. This didn't seem to make a difference, other than preventing the warning when Memory Profiler detected the activity of other application domains.
mgweeks wrote:Firstly, I'm very impressed with this software. I've been trying to solve memory leaks an application and managed to close a couple of loopholes that had cropped up. I've got one last one that is causing objects to stay in memory and the root path only shows up if I unselect "Only include identified roots". I think the documentation is unclear about exactly what unidentified roots are. What are they if not one of the identified types?

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Post by Andreas Suurkuusk » Thu Jan 19, 2006 8:23 pm

One thing that I didn't mention in my first post, is that static value type fields are not evaluated. So if you have a struct that contains a reference field, and you have static field using that struct, then this will not be identified as a root. It's possible that this is why the profiler fails to identify the root of your instance.

E.g. consider the following code:

Code: Select all

struct SomeStruct
{
  internal SomeClass someVar;
}

class SomeClass
{
  static SomeStruct someStruct;

  static SomeClass()
  {
    someStruct.someVar = new SomeClass();
  }
}
In this example, the SomeClass instance referenced by SomeClass.someStruct.someVar will not have an identified root.

Roots like this will be identified in a future version of the profiler.
Best regards,

Andreas Suurkuusk
SciTech Software AB

clintmiller

Post by clintmiller » Thu Jan 19, 2006 9:45 pm

Although this might be the case, I don't believe that applies for me. Any other ideas?
Andreas Suurkuusk wrote:One thing that I didn't mention in my first post, is that static value type fields are not evaluated. So if you have a struct that contains a reference field, and you have static field using that struct, then this will not be identified as a root. It's possible that this is why the profiler fails to identify the root of your instance.

E.g. consider the following code:

Code: Select all

struct SomeStruct
{
  internal SomeClass someVar;
}

class SomeClass
{
  static SomeStruct someStruct;

  static SomeClass()
  {
    someStruct.someVar = new SomeClass();
  }
}
In this example, the SomeClass instance referenced by SomeClass.someStruct.someVar will not have an identified root.

Roots like this will be identified in a future version of the profiler.

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Post by Andreas Suurkuusk » Mon Jan 23, 2006 12:06 pm

I don't have any other ideas on why the profiler fails to identify the roots of your instance. As was noted in the original reply, it is possible that the profiler fails to evaluate local variables and argumentsm depending on the state of the program when a snapshot is collected.

If you send us some log-files from the profiler it is possible that we can find out why the profiler fails to identify the root.

To create the log files you must supply the "/log" command line argument to the profiler executable (NetMemProfiler.exe). This will create three log-files in the program directory: ProfilerLog.txt, ProfilerClientLog.txt and AssertLog.txt (AssertLog.txt will probably be empty). After you have created the log-files, you can send them to support@scitech.se (preferably zipped).
Best regards,

Andreas Suurkuusk
SciTech Software AB

Post Reply

Who is online

Users browsing this forum: No registered users and 34 guests