Click here to Skip to main content
15,886,199 members
Articles / Web Development / CSS

Silverlight application memory leaks detector

Rate me:
Please Sign up or sign in to vote.
4.15/5 (10 votes)
11 Feb 2009CPOL3 min read 55.5K   785   26  
Simple memory leaks detector for Silverlight applications.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;

namespace Keybitz.Common.MemoryProfiler
{
    public class MemoryProfiler
    {
        #region private members
        private static object lockObject = new object();
        private static List<ObjectStruct> elementsList = new List<ObjectStruct>();
        private static int generationCounter = 0;
        #endregion

        #region innerClass
        private class ObjectStruct
        {
            public WeakReference Reference;             // weak reference to the monitored object
            public int Genereation;                     // the generation of the monitored object
            public string StackTrace;                   // stack trace string of when the object was created
            public bool DisposedSignaled;               // true if the Dispose() function of the object was called

            public ObjectStruct(WeakReference _Reference, int _Generation)
                : this(_Reference, _Generation, null)
            {

            }

            public ObjectStruct(WeakReference _Reference, int _Generation, string _StackTrace)
            {
                Reference = _Reference;
                Genereation = _Generation;
                StackTrace = _StackTrace;
                DisposedSignaled = false;
            }

            public override string ToString()
            {
                return Genereation.ToString() + ": " + Reference.Target.ToString() + ". Disposed signal = " + DisposedSignaled.ToString();
            }
        }
        #endregion

        #region public methods

        /// <summary>
        /// Call this method from within the constructor of the monitored object
        /// </summary>
        /// <param name="obj">The object to monitor</param>
        [Conditional("DEBUG")]
        public static void AddReference(object obj)
        {
            lock (lockObject)
            {
                // avoiding dups - can happen when adding an element and its base-class to the profiler
                if (elementsList.Any(p => p.Reference.IsAlive && p.Reference.Target == obj))
                    return;
                elementsList.Add(new ObjectStruct(new WeakReference(obj), generationCounter, new StackTrace().ToString()));
                //elementsList.Add(new ObjectStruct(new WeakReference(obj), generationCounter, null));
            }
        }

        /// <summary>
        /// Call this method whenever you want to check the current memory's state
        /// </summary>
        [Conditional("DEBUG")]
        public static void Check()
        {
            lock (lockObject)
            {
                long memUsage = GC.GetTotalMemory(true);
                for (int i = 0; i < elementsList.Count; i++)
                    if (!elementsList[i].Reference.IsAlive)
                        elementsList.RemoveAt(i--);
            }
            generationCounter++;
            Debugger.Break();
        }

        /// <summary>
        /// Call this function from within the Dispose() method of the monitored object
        /// </summary>
        /// <param name="obj">The object to signal its disposal - should be in the profiler already!</param>
        [Conditional("DEBUG")]
        public static void SignalDisposed(object obj)
        {
            lock (lockObject)
            {
                var objectsToSignal = elementsList.Where(p => p.Reference.IsAlive && p.Reference.Target.Equals(obj));
                if (objectsToSignal.Any() && objectsToSignal.Count() == 1)
                {
                    var objectToSignal = objectsToSignal.First();
                    objectToSignal.DisposedSignaled = true;
                }
            }
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer Semantinet
Israel Israel
Graduated from the Ben-Gurion University of the Negev, Israel, with a B.Sc in Communications systems engineering.
Worked for Intel for a short period and currently working @ www.headup.com

Comments and Discussions