There have been a few reports of memory leaks in recent versions of SourceTree for Windows. We understand these kinds of issues can adversely affect the SourceTree experience and are important to identify and address. Memory leaks can be tough to handle, and is compounded with applications written using a managed language (like SourceTree) as lifetime tracking of objects tend to be fairly complex. Here’s one such memory leak that we fixed in 1.9.9 for Windows that we released last week.
Identifying the leaky object
How does a memory leak appear? Most of the time it’s a fairly simple case of “I created some objects, and when I was done using those objects something was still referencing them”. In this case, identifying what was leaking in SourceTree was an easy task:
Hint: the sidebar isn’t showing more than 100 items and there’s only a single SidebarNode for each item…
Determining the cause
Most of the time the cause of a leak is easy to spot:
- An event handler is still subscribed
- The object is not being removed from a list or is still held on to as a direct reference
- An unmanaged object wasn’t disposed/cleaned up
However, the real difficulty isn’t figuring out if you have a leak – the challenge lies in figuring out what’s causing it to happen. In this case, I suspected that our UI library that quickly draws the sidebar was doing something wrong, and that it might be holding onto objects that it shouldn’t. After looking at the memory dump it was clear that assumption was correct:
That’s more than 4x the correct number of nodes. Okay, so now we know that it involves the SidebarNode and the TreeNode objects. The TreeNode holds a reference to the object it’s showing to the user, so something must be keeping a reference of it around, which is keeping our massive count of SidebarNodes around too.
After taking a peek into the the TreeNode class, there were a few issues (oops):
- A subscription to an event handler wasn’t unsubscribed
- The TreeNode objects were added to a cache and never removed from that cache
To make sure these two things were actually causing the leak, we created a simple demo app was created that added and removed items in the tree thousands of times. Creating a small test app made it much easier to track where the nodes were created, and why they didn’t get cleaned up properly. It also ensures we can test this again in the future to prevent regressions. After running the tests, it appeared that the leak was fixed. As mentioned earlier this fix has been rolled out in 1.9.9 for Windows, and should address the memory issues we were seeing. Check it out for yourself!