I've been busy showing off the work we've been doing in WPF to our clients, both in the UK, and in Las Vegas at a tradeshow. We had ramped up to these events and while we had a very nice, working application the performance was just terrible. We were hoping SP1 of the .net framework 3.5 would fix things, but when we installed Beta 1 of this it didn't fix our performance headaches. Off of the tight deadline I was able to do some code profiling and found my problems.
To sum things up, any time you are loading up a resource dictionary you will take a performance hit. Do a search in your code ASAP for "= New Uri" across your application and ask yourself "when does this get called?" If its called frequently consider caching the resource at the module or global level of your application and re-using the copy in memory, your application will run much faster for it.
My listboxes were using a multi-valueconverter to determine which image to display in the template next to the text for the listbox. What I discovered was that the convert method of the multi-valueconverter was creating a new object of a utility class that I have to work with a large resource dictionary containing vector images. On the constructor for that class I was calling the following code:
mobjResourceDictionary = New ResourceDictionary
mobjResourceDictionary.Source = New Uri("pack://application:,,,/UtilLib;component/VectorImages.xaml")
So for each item in the listbox it was loading this resourcedictionary. That was my bottleneck. My solution was to declare my utility class at the module level in my IMultiValueConverter class and on the constructor create the new object of the utility class, then use that object in the convert routine. Since it only loads the resource dictionary one time (at load time of the app in fact) the render of the list box went from taking 3 seconds with 200 items to under a second (instantaneous to the user). Further, because I am using a virtualizing stack panel in my listbox template, scrolling the listbox is now smooth whereas in the past it was choppy.
I went through my application and noticed several other places where I was loading up resource dictionary objects. I decided that I would avoid this at all costs, loading them once preferrably when my splash screen was up and then re-usuing the global resourcedictionary objects that I create at that time across my application. Once I did this I fixed a ton of performance problems. For instance, I had code that was loading a resource dictionary up in my gotfocus/lostfocus events of a control I wrote that was drastically slowing things down.
While it seems so obvious now, a lot of the sample/demo code out there arbitrarily loads resources up. In practice this SHOULD NOT BE DONE frequently, you should load your resource dictionary up and startup and re-use your object in your app to keep it in memory. Taking this approach has drastically increased the speed of my application.
Sean