Instance counting with Autofac

You want to do what?

In a recent project I had a problem with some form of memory leak. Since the project used Autofac I figured that we could use it to find likely sources for the leak.

The solution? Adding a new Autofac module that we can hook up in the bootstrapper.

Note that you do not want this to run in production, so remember to use some form of DEBUG flag condition in the BootStrapper.

The event “Activated” on the IComponentRegistration object will trigger for each object Autofac resolves. So all we need to do now is to keep track of those objects.

The class InstanceCounter will help us with that

As you might note from the naming, this class were slapped together without to much afterthought. We never return anything from the functions, but rather we send in Actions and Funcs in order to make it possible for us to use Conditional attributes.

The class works by having a backing dictionary where we insert each item using a WeakReference with their hashcode as the key.

Example of how to use the InstanceCounter

Example output from this call

TopObj 1) Foo:10
TopObj 2) Bar:6
TopObj 3) FooBar:4
TopObj 4) FooBarBaz:2

Where the number on the end marks the number of living instances.

 

This Post Has 7 Comments

  1. Beautiful, and great post, thanks.

    Out of curiosity: did you find any leaks with this?
    Knowing what those leaks were, could they have been easily spotted another way?

    1. Thanks, we did find a few leaks using this. Or rather, we managed to identify the classes that we needed to dig deeper into. A lot of code reading were needed to figure out the exact nature of the issues.

      Using a regular memory profiler could have worked as well. But then we would need to sift through data that we didn’t need.
      The biggest win,according to me, with this solution were that we could use the data from testing sessions without the hassle of having the profilers running all the time.

      1. Finding the classes is the main thing imho.
        I’ve used weak ref’s before to hunt down mem problems, really nice, lightweight solution.

        So how did you go about collecting the mem counters after testing sessions? A debug view in the app? Stored logs?

        1. We had a debug page in the app where we listed the full list. A simple free text filter were added so we could quickly check out if any View Models were doing anything they shouldn’t.

          We only went for in-memory storage. After a test session the devs could take the phone and quickly check the memory usage/living instances. We never needed anything more complex than that.
          For the everyday development we hooked up a hardware button on our device to “PrintTopLiveObjects”. This allowed us to print the top ten types in the debug-log any time we felt like it.

  2. Please correct me if I’m wrong, but I think I spotted a possible bug in line 21 of InstanceCounter. Shouldn’t it be something like _list[RuntimeHelpers.GetHashCode(o)] = ... to ensure that you don’t call an override method? And I think it’s then still possible that two objects have the same hash code, isn’t it?

    1. That is correct, this solution is really more of a quick and dirty way of getting some bearing of where the(perceived) problems lies.
      So in the use case we had we were fine with losing a few instances due to the possibility of collisions.

      However we definitely should have used RuntimeHelpers.GetHashCode as you noted. I have updated the example in order to limit the flaws. Good catch!

  3. Hi, and thank you for this post. We used it to verify a change of how we are using Lifetimescope. I removed the mutex and are instead using ConcurrentDictionary. Which removed some complexity.

Leave a Reply

Close Menu