Along with painting the big picture of our performance efforts I’d like to share a few specific things we’ve learned along the way. The first is hosting a WPF window inside a Windows Forms Window.
We’ve spent a lot of time looking at memory usage over the past several months and one of the things that we saw was that some tool windows were causing surprising growth in memory usage. We tracked the problem down to hosting a WPF control inside a WinForms window wrapper. I’m particularly close to this one because the issue was discovered by the TFS team. We’ve done some cool visualizations in this release (like branch hierarchy and merge visualization, etc) and we chose to use WPF to create them to get really nice looking images. We found that we had 3 tool windows in version control alone that used this. I know there are others. Once we shared the learning with the rest of the division, I heard anecdotal reports from other areas of the product but I never did a full tally.
The situation is this…
WPF can not render natively into a Windows Forms window. Instead it renders into memory and “bitblts” it into the WinForms window. We observed that, in our VS tool windows, there was about a 20MB memory cost for each tool window to do this. Further we saw transient incremental memory allocation as the tool windows were resized of about 4MB per resize (although it was garbage and the GC would eventually reclaim it).
We have solved the problem by eliminating the intermediate WinForms wrapper windows in the WPF tool window chain (VS now provides a native WPF root level tool window).
This change has saved dozens of megabytes in some VS scenarios and is something you should be thoughtful about as you look at extending Windows Forms applications with new WPF components.