dinsdag 27 december 2011

Memory profiling a Silverlight Application

It’s the nightmare of most developers:  a memory leak.  Not knowing which pesky reference is holding that object in its grip or what eventhandler refuses to let go of that viewmodel.  Today I’ve had the tremendous joy (notice the sarcasm please) of solving a memory leak.  To make matters even worse, the memory leak was caused by a Silverlight application.  I’ve seen a couple of suggestions for memory profiling a Silverlight application like Davy Brion’s solution, or even tried out a couple of memory and performance profilers like the one of Jetbrains, but none that felt comfortably to work with and looked too complicated for such a simple issue.

Then after I was just about to give up, I came across RedGates ANTS memory profiler.  At first I was skeptic because it seemed like a sales person wrote the introduction page of the tool but I was pretty desperate so I filled in my personal data and downloaded the trial.  Beware though cause RedGate actually uses your data to call you later on to get feedback and to try to talk you into buying their products.

The installation was easy and straightforward and after restarting visual studio I saw the ANTS submenu appear in the menu bar.  It didn’t take me much longer after that to find the memory leak.
The actual memory leaked wasn’t mine but was introduced by a class I found on the internet, the bindinghelper http://www.scottlogic.co.uk/blog/colin/2009/02/relativesource-binding-in-silverlight/ ).  The class helps a Siverlight developer to relatively bind to a property outside a datatemplate or whatever.  

Let me explain how I found the memory leak:

At first I launched the ANT memory profiler by clicking ANTS => Profile Memory.  It then started profiling my webpage by default so I stopped profiling and then clicked File => New Profiling Session.  It then launched to following screen:



I switched the Application Type to profile to Silverlight 4 and filled in the Silverlight Application URL.  After that I clicked Start Profiling.  

After some profiling it was very obvious I was dealing with a memory leak here:



So I then took a memory snapshot:



So now what is causing this dammed memory leak?   I then clicked the Class List button which gave me a list of classes and how many instances there were and how much memory it consumed.  



I then clicked the Instance Categorizer to see the dependency graph that references all these strings.  On the far left of the screen I saw the cause of all my troubles :-).



I immediately opened the BindingHelper class and saw that objects added to its dictionary weren’t removed when they weren’t needed anymore so it was just a matter of adding the right line and voila! Memory leak solved ;-)

From this I can draw two conclusions:

The first is never to trust code coming from the internet.  Allot of bloggers submit code that hasn’t been tested on the long run and is merely intended as a reference and not as a solution.

The second is that RedGates ANTS memory profiler is one sweeeeet profiler.  You don’t have to be a rocket scientist to use it and it show some nice graphs, and admit it, who can say no to pretty graphs and diagrams. 

Till next time!

donderdag 8 december 2011

Legacy code retreat

This Saturday I had the privilege of attending another code retreat, only it wasn’t just a normal everyday code retreat but a legacy code retreat! This code retreat was hosted by J. B. Rainsberger so big thanks to him!

Whats the difference?

The basic setup is pretty much the same.  You pair with another coder and start an intensive 45 minutes session of coding.  After each session there is a retrospective of what kind of stuff you tried and how well it went.  The big difference in between a normal code retreat and a legacy code retreat is that you don’t start from scratch but you begin with an existing code base.  It is then your task to refactor the code as best as you can in 45 minutes without breaking existing functionality.

Test as documentation and failsafe

The first session wasn’t that special.  The code was handed to us and the purpose was to try and figure out what it does.  I started out writing tests for the class with the most behavior and just started from top to bottom to figure out each individual behavior.  I enjoyed this allot because not only do you get to cover the existing code with tests so you wouldn’t break the functionality when refactoring later, the tests in itself is an excellent way of discovering how the code base works and behaves.

After the first session a retrospective was held and it was surprising to see how many pairs actually didn’t even run the code!  To be honest I didn’t run it too.  Another surprising feat was that some couples even managed to find bugs in the code from the first couple of unit tests!

The golden master

So then came the second session.  Here we were asked to write end to end tests with a technique called the golden master.  The idea behind this is that you save the output of the program to a separate file.  There should be enough variation in the input of your parameters to try and cover as much of your program as possible.  As a rule for the code handed by us, we wrote away 10.000 different variations of the parameters. The output you’ve written away should be confirmed as the correct behavior of the program as it will be used as a reference for the next tests.

When you refactor the code you can then run the golden master to save the output of the refactored code.  The correctly verified output will then be compared to the output of the refactored code and any differences between the two will be displayed.

This technique is very useful for when you have an application with zero tests in it and the code is too coupled to test.  You can then slightly change the code to make unit testing easier and still have a small safe-zone in which you can verify the correctness of your application.

Some couples (including me again -_-‘ ) tried to save all the possible values the parameters could form.  This turned out to be a mistake as the variations ran up to a couple of millions.

I did have one issue though and that is that if you weren’t able to get the end to end tests done in this exercise you didn’t have a backup testing mechanism in the other sessions.  I addressed this to JB and he said he was going to plan to upload the Golden Master so that next code retreat this wouldn’t be a problem any more.

Mocking behavior by sub classing

This technique was already known to me but I didn’t know it would prove as useful as it did when dealing with legacy code.  Subclass To Test… basically the name says it all.  When to code has a strong coupling to it and mocking behavior of the class proves difficult we can make the methods of that class virtual (overridable/@override).  We can then subclass this class and override the methods that we want to mock in order to test our initial method.  I’ll demonstrate this by some code:

Say we have the following legacy code:

public class BootyShaker
{
    private List<string> _booties;

    public int NrOfBooties
    {
        get { return _booties.Count(); }
    }

    public void CreateSomeBooties()
    {
        _booties = new List<string>();
        // Legacy code should contain magic numbers!!!
        for (int i = 0; i < 12; i++)
        {
            _booties.Add(CreateBooty());
        }
    }

    /// <summary>
    /// Disclaimer: I do not take any responsibility for suicides as a consequence of utilizing this method
    /// </summary>
    /// <returns></returns>
    public string CreateBooty()
    {
        string thaBootie = string.Empty;
        // Some complex behavior
        return thaBootie;
    }

}

So we want to test the CreateSomeBooties method but the developer didn’t make it easy for us.  To make matters even worse the CreateBootie method is called by a couple of dozen other methods that we haven’t tested yet!  So in order to mock the behavior without interfering with the rest of the untested (!) code we’ll subclass the BootyShaker.

public class BootyShaker
{
    private List<string> _booties;

    public int NrOfBooties
    {
        get { return _booties.Count(); }
    }

    public void CreateSomeBooties()
    {
        _booties = new List<string>();
        // Legacy code should contain magic numbers!!!
        for (int i = 0; i < 12; i++)
        {
            _booties.Add(CreateBooty());
        }
    }

    /// <summary>
    /// Disclaimer: I do not take any responsibility for suicides as a consequence of utilizing this method
    /// </summary>
    /// <returns></returns>
    public virtual string CreateBooty()
    {
        string thaBootie = string.Empty;
        // Some complex behavior
        return thaBootie;
    }

}

[TestFixture]
public class BootyShakerTest
{
    [Test]
    public void CreateSomeBooties_should_create_12_booties()
    {
        var bootyShaker = new BootyShakerSubclassTest();
        bootyShaker.CreateSomeBooties();
        Assert.AreEqual(bootyShaker.NrOfBooties, 12);
    }

}

public class BootyShakerSubclassTest : BootyShaker
{
    public override string CreateBooty()
    {
        return "Mah booty";
    }
}

We need to make the method that we want to mock virtual (or overridable) so we can change the behavior in the subclass.  Then when we have successfully mocked the behavior we can write a test for the original method.  When the test is written we can refactor CreateSomeBooties.

Delegate the call by using Subclass To Test

In the session after that we went a step further.  Now that we’ve created the base class that mocks the behavior of the CreateBooty method we can refactor this method to the appropriate type and delegate the call.  Phew… I think I’ve lost you there :-P.  I’ll try to speak the universal language then… code:

So simply put the CreateBooty behavior doesn’t belong inside the BootyShaker so we’re going to try and extract the behavior out of the class.  So the first thing we need to do is inject the new type into the original BootyShaker:

public interface IBootyCreator
{
    string CreateBooty();
}

private readonly IBootyCreator _bootyCreator;

public BootyShaker(IBootyCreator bootyCreator)
{
    _bootyCreator = bootyCreator;
}

Don’t forget to adjust your base class to so you can still run your test:

public BootyShakerSubclassTest(IBootyCreator creator):base(creator)
{
       
}

Then refactor away the code in our base class inside a mock:

public class MockBootyCreator : IBootyCreator
{
    public string CreateBooty()
    {
        return "Mah booty";
    }
}

Then delegate the call in our BootyShaker:

public virtual string CreateBooty()
{
    return _bootyCreator.CreateBooty();
}

And then remove the base class and use the original Bootyshaker with the injected 

MockBootyCreator:

[Test]
public void CreateSomeBooties_should_create_12_booties()
{
    var bootyShaker = new BootyShaker(new MockBootyCreator());
    bootyShaker.CreateSomeBooties();
    Assert.AreEqual(bootyShaker.NrOfBooties, 12);
}

So now you’ve coupled away the responsibility of creating booties to a new type!

Extracting pure functions

The next session was a bit different.  This time we had to refactor by extracting pure functions.  The good thing about doing this is that you do not alter the state of the object in which you’re working thus this makes it very easy to test.

This wasn’t really new to me and I try to do this as much as possible since working without state reduces allot of the risk and makes testing allot easier.

Actually do stuff

The last 2 sessions JB decided to do something different.  This time we weren’t required to throw away our code so we could actually get some work done! To be honest, at the end of the day my head felt like it was going to explode so I needed the two extra sessions to be a bit more productive.

The problem I had with the two sessions is that you still had to switch pairs.  You would then have to adjust to the code of your new partner.  I would think it would be better if it was just one extra-long session since it takes a couple of minutes to get into each other’s mindset.

So that was it for the legacy code retreat.  Big thanks to Erik for the organization and to JB for taking the time to guide us :-).

Join us next time!  Till then...