个人主页

转载 Davvy Brion - object tracker

One of the downsides of working with a young platform like Silverlight is that the tool support isn't quite 'there' yet, particularly when it comes to profiling for performance and memory usage. And as you may or may not know, Silverlight makes it very easy to introduce memory leaks into your code. Since you can't just attach a memory profiler to your Silverlight application, optimizing memory usage or tracking down a leak can be a real pain in the ass.

In the past i have resorted to grabbing a memory dump of the browser and analyzing the content of the managed heap with windbg to track down which instances where being kept in memory. While this works, it's pretty time consuming and can quite easily lead you down the wrong path. One of the most important things that you want to know in this specific case is: which types are being kept in memory, and how many of them?

In this case, being able to query something during debugging regarding which instances are still kept alive in memory at certain times is sufficient for me. So i came up with the following class:

    public static class ObjectTracker

    {

        private static readonly object monitor = new object();

        private static readonly List<WeakReference> objects = new List<WeakReference>();

        private static bool? shouldTrack;

 

        public static void Track(object objectToTrack)

        {

            if (ShouldTrack())

            {

                lock (monitor)

                {

                    objects.Add(new WeakReference(objectToTrack));

                }

            }  

        }

 

        private static bool ShouldTrack()

        {

            if (shouldTrack == null)

            {

                shouldTrack = Debugger.IsAttached;

            }

 

            return shouldTrack.Value;

        }

 

        public static IEnumerable<object> GetAllLiveTrackedObjects()

        {

            lock (monitor)

            {

                GC.Collect();

                return objects.Where(o => o.IsAlive).Select(o => o.Target);

            }

        }

    }

The idea is basically to just keep a list of WeakReferences of objects you want to track (only if a debugger is attached), and later on you can 'query' the live instances through the GetAllLiveTrackedObjects method. This method obviously performs a full garbage collect to make sure only objects that are really still alive are returned. Again, you should almost never do a GC.Collect() manually, but in this case the method will only be called while you're debugging.

Then, you strategically put the following line in the constructor of every kind of type you'd like to track:

            ObjectTracker.Track(this);

I have that line in the constructor of my base View class, my base Controller class and in my base Disposable class. So now, when i want to check if there are any dangling references to instances of types that i really don't want hanging around, i can just do something like this:

            var liveObjects = ObjectTracker.GetAllLiveTrackedObjects();

 

            if (Debugger.IsAttached)

            {

                Debugger.Break();

            }

And then manually inspect the content of the liveObjects collection. It's far from perfect, but at least it's an easy way to at least know which instances (that i care about) are being kept in memory. It'll do until we get better tool support :p

 网址:http://davybrion.com/blog/2009/08/tracking-dangling-object-references-in-silverlight/

posted on 2011-04-29 13:26  beck99  阅读(275)  评论(1编辑  收藏  举报