Today I’m going to change the subject a bit! Even that is still based on Qt it only touches GitQlient tangentially. This time GitQlient is the test environment and thing to show is the Deleaker review!
Artem contacted me a long time ago and my plan was to publish a post before the word pandemic became mainstream. Unfortunately, for obvious reasons I’ve had to delay it until I found time.
I never checked how GitQlient was doing it with the memory before. Mainly because I trusted Qt handling it for me. That’s fine most of the time but is also a bit error-prone since GitQlient is doing a lot of things. And not always they are under Qt’s radar.
Nowadays, I’m keeping GitQlient running more than usual. That made me realize that memory is really important so it doesn’t swallow all the RAM in the computer. During Christmas I finally found some time to go back to my Windows partition to test Deleaker with GitQlient.
After some time with it I think I’ve learned a bit about how it works. So here are some of my thoughts!
For the test I’m using Visual Studio 2019 Community, although Deleaker also works with Qt Creator and it has a really nice integration. I’m using all the allocation types because I wanted to see everything although in my case I was interested in the memory ones:
The first test I did was to run GitQlient, open a repository and closing it without interacting with Git at all.
Deleaker allows you to take Snapshots and that’s a really powerful tool I’ve used during the whole test. In Visual Studio, you just need to go to Extensions -> Deleaker -> Deleaker Window. In the top left you can see the option Take Snapshot and that’s the one I press every time I did a significant change.
For this Deleaker review I used 3 snapshots in addition to the last one that Deleaker automatically creates. After you take a snapshot, the stack trace will be available for you to dig into it. So there is no need to wait until the final execution and remember what each snapshot was about. After the very first snapshot I got the following stack trace:
This scared me a lot, because I wasn’t expecting to get so many leaks to start with. But I was wrong: when I took the snapshots, the objects are attached to the life of their parent widget. So, for now I don’t need to worry!
Next step was to open a repository, take a snapshot and right after that, close it taking another snapshot afterwards. This is a summary of the snapshots I took:
- After GitQlient starts
- Once a Git repository is open
- After closing a Git repository
- Diff between #2 and #1
- Diff between #3 and #1
- Automatic snapshot after closing GitQlient
In Deleaker you can see the diff between two snapshots by clicking on the Compare with… button. That let’s you select the snapshot you want to compare with.
That’s a nice feature but I was confused since I expected to see the subtraction between both snapshots. What it seems not to be the case at least as straight-forward as I thought for the Snapshot #4.
I compared the status after I closed the repository and this time the results where way better. Deleaker actually detected several leaks I was having!
One of them was located in GitRepoLoader class: I just forgot to use smart pointers!
Deleaker also help me finding a really nasty bug/leak that was quite challenge to fix. It involved threads and singletons and it was hard since it was during tearing down the app. The problem is apparently that the deleteLater() was not being called (or maybe not detected by Deleaker, since it’s managed by Qt). Digging more I found that QLogger had an issue when tearing down and sometimes I was actually leaking, so I did a refactor on it.
Another leak was in IssueDetailedView. According to Deleaker it was leaking all around and that was weird:
This was a especially difficult case to find the leak since the stack trace shows the creation of the object but nothing else. After digging a bit where this class is used I found that I was deleting layouts but not their content:
Checking the RAM usage
Another tool that I wanted to use is the RAM analyzer to see how much memory GitQlient is using and if it’s freeing it. I’m not entering in detail about how Qt works and what I can do for that (probably needs a post or a series of them). For the Deleaker review is to see how it performs compared to the Visual Studio tool.
For this case unfortunately I have to say that Visual Studio provides a better integration feature. On Deleaker I missed a mark in the RAM history for when I took the snapshot and to be able to scroll no it’s usage. On Visual Studio I’m able to tooltip the amount of memory that GitQlient was using in a specific moment:
Finally, one thing that needs improvements is the over-watch of the RAM when it’s being freed. On Deleaker I didn’t manage to get any significant change in the graph and that difficult me this specific task:
Deleaker review: some final thoughts
I feel that the Deleaker brings a more powerful UI that the tool that Visual Studio uses for the stack trace. It also detects (or at least shows) the files and lines way better and it allows you to select the module you want to process, so you can discard false positives really quick.
The integration with Qt applications makes it way more intuitive and easier to use that the Visual Studio tool. Especially when it comes to identify the file and line that is the root cause of the leak. On Visual Studio that gets quite messy when it comes to show the allocations.
In the performance part, I would like to see some more UI interactions with the RAM graph, especially when linked with snapshots. This can is a very powerful tool if you want to check not only leaks but performance.