Every WPF developer knows the situation where you have a large line-of-business application, you’ve implemented all the features and when you finally run it on real data – it runs s-l-o-w.
Optimization for performance is fun since a 1% change of code gets you 99% change in performance. However, finding the one location you should change can be a pain.
This is why we’ve invented performance profilers. Profilers can help you pin-point the problem.
WPF applications performance problems can usually be categorized to several kinds, for example, layout related, rendering related, etc.
Following is a nice list of common places to optimize when you work with WPF applications.
Microsoft provides a profiler specifically tuned for finding WPF related issues. You can find the installation guidelines on MSDN.
Note: if this is the first time you use it, and you don’t get the data, try the patch mentioned in this post.
When the profiler does work, it produces very interesting information.
For example, in the following image we can see the visual tree on the left and in it the hot element (painted red) where a lot of CPU cycles went (either due to rendering or layout).
You can also see different categories of WPF (dispatcher related, layout related, rendering related, etc.) on the right and how much they affect the running application.
For more information I suggest you read on MSDN on how to work with this excellent tool, but now I want to discuss a different aspect of it.
Real Life Scenario
On real life applications the visual tree on the left can get quite big and the fact is that when you go too deep with the tree control the WPF profiler crash! Usually with an error similar to this:
The problem is that the tree got too deep and WPF itself doesn’t support it.
What I would have liked from MS is a button that lets me set the current element as the new root of the tree so I could continue my search on the visual tree to find the hot element. Or at least provide the code for the WPF profiler, so I could do this myself.
Unfortunately, none of these options are available so I was forced to find a different solution.
What I did was a little hacky, but nevertheless provides a solution to the problem.
The WPF profiler works with plugins. In fact the Visual Profiler itself is implemented as a plugin which comes by default.
So I’ve create a new plugin, which I called “My Visual Profiler”. My plugin aggregated the original plugin and adds a button on top of it. Then, using some nasty reflection I modify the tree so that the currently selected item in the tree is added to the root element. This enables me to continue debugging and effectively remove the limitation I previously had.
If you come across the same problem, you can use my plugin, provided here.