Building root paths using external API

Use this forum for questions on how to use .NET Memory Profiler and how to analyse memory usage.
Post Reply
softprovlad
Posts: 1
Joined: Thu Jun 04, 2009 7:36 pm

Building root paths using external API

Post by softprovlad » Thu Jun 04, 2009 7:53 pm

Hello,

We are using the external API (SciTech.NetMemProfiler.Core dll) to automate the process of detecting memory leaks. We can start the application under the profiler, collect snapshots, compare snapshots and extract type and instance information.

However we can't seem to find a way to build root paths for a given type instance. We're trying this:

RootPath[] rootPaths = _session.Comparison.GetRootPaths(instanceId, true, true);

which gives us an array of root paths. But each RootPath object only seems to expose the root object, and we cannot figure out a way to build the full path from our specific instance to the root object.

Do you have a code sample that shows how to accomplish this?

Thank You,
Vlad

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

Post by Andreas Suurkuusk » Fri Jun 05, 2009 2:38 pm

To get information about the instances that are included in the root path, the method RootPath.GetObjectEntries should be used. Below I have provided an example program that shows how you can present the root paths for an instance. Note that the names of classes and methods related to root paths will change in .NET Memory Profiler 3.5. (Version 3.5 will also provide additional information in the root paths, such as the field for each instance).

Code: Select all

using System;
using SciTech.NetMemProfiler;

namespace ProfilerCoreTest
{
    class Program
    {
        static void Main( string[] args )
        {
            ProfilerApplicationCore app = new ProfilerApplicationCore();
            //
            // Load a session and retrieve information about the first
            // snapshot (by comparing with Empty)
            //
            using( ProfilerSession session = app.LoadSession( @"<path to session file>" ) )
            {
                SnapshotHeader[] snapshotHeaders = session.SessionFile.GetSnapshotHeaders();
                if( snapshotHeaders.Length > 0 )
                {
                    using( ProfilerComparison comparison = app.CompareSnapshots( 
                        snapshotHeaders[0], SnapshotHeader.Empty ) )
                    {
                        // Get the type we're interested in
                        ManagedType type = session.GetMatchingType( "<SomeTypeName>" );
                        TypeInstanceId[] instances = comparison.GetTypeInstances( type, true );

                        if( instances.Length > 0 )
                        {
                            // Present the root paths for the first instance of 
                            // the type.
                            RootPath[] rootPaths = comparison.GetRootPaths( 
                                instances[0], true, true );
                            foreach( RootPath rootPath in rootPaths )
                            {
                                WriteRootPathInstances( comparison, rootPath );
                                // End the printout with root information.
                                WriteRoot( rootPath.RootReferee );
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Writes all the instances in a root path
        /// </summary>
        private static void WriteRootPathInstances( 
            ProfilerComparison comparison, RootPath rootPath )
        {
            Console.WriteLine( "---Root path---" );
            // Get the instances that are part of the root path.
            // The first instance is the closest to the root.
            TypeInstanceId[] rootInstances = rootPath.GetObjectEntries();
            // Write the root path instances in reverse order
            // to match the behavior in .NET Memory Profiler
            // (with the root at the bottom)
            for( int i = rootInstances.Length - 1; i >= 0; i-- )
            {
                TypeInstance instance =
                    comparison.GetTypeInstance( rootInstances[i] );
                Console.WriteLine(
                    instance.InstanceType.Name + " " + instance.ToString() );
            }
        }

        /// <summary>
        /// Writes information about a root referrer.
        /// Will include a bit more information than RootReferee.Text.
        /// </summary>
        /// <param name="rootReferrer"></param>
        private static void WriteRoot( RootReferee rootReferrer )
        {
            switch( rootReferrer.RootType )
            {
                case RootType.StaticField:
                    {
                        // It's a static field root. 
                        // More information can be retrieved by casting 
                        // to StaticRootReferee
                        StaticRootReferee staticRoot = (StaticRootReferee)rootReferrer;
                        Console.WriteLine( "Static field: " + 
                            staticRoot.ClassInfo.Name + "." + staticRoot.Field.FieldName );
                        break;
                    }
                case RootType.Argument: // Will only appear in .NET 1.x
                case RootType.Local:    // Will only appear in .NET 1.x
                case RootType.Method:
                    {
                        // It's a method root (local field or argument). 
                        // More information can be retrieved by casting 
                        // to MethodRootReferee
                        MethodRootReferee methodRoot = (MethodRootReferee)rootReferrer;
                        Console.WriteLine( "Method: " + 
                            methodRoot.ClassInfo.Name + "." + methodRoot.Function.Name );
                        break;
                    }
                case RootType.GCHandle:
                    {
                        // It's a GC handle root 
                        // More information can be retrieved by casting 
                        // to GCHandleRootReferee
                        GCHandleRootReferee gcHandleRoot = (GCHandleRootReferee)rootReferrer;
                        Console.WriteLine( "GCHandle: " + 
                            gcHandleRoot.GcHandleInstanceId );
                        break;
                    }
                case RootType.Finalizer:
                case RootType.Other:
                    {
                        // It's a finalizer root or some other root.
                        Console.WriteLine( rootReferrer.Text );
                        break;
                    }
            }
        }
    }
}
If you need any additional help to get this to work, please reply to this post.
Best regards,

Andreas Suurkuusk
SciTech Software AB

Post Reply

Who is online

Users browsing this forum: No registered users and 21 guests