WPF XAML Resource Benchmark

WPF is very dynamic and allows us to use resources in many different ways. We can use Static or Dynamic. We can place all our resources in App.xaml or use merged dictionaries each time.

You can see all the approaches and what I think is best practice in my WPF Merged Dictionary problems and solutions post.

If you’re new to WPF resources, I suggest reading my Explicit, Implicit and Default styles in WPF post before diving into this one.

This benchmark is supposed to show, in numbers, how any approach affects performance.
Here’s what I want answered with this benchmark:

  1. Is splitting resources in App.xaml to many Merged Dictionaries file vs. one long App.xaml file means longer application startup time?
  2. Is loading all resources in App.xaml once better than loading the resources every time with merged dictionary?
  3. Is DynamicResource instead of StaticResource an issue? How big of an issue?’

Before answering any of those, there’s an important thing to understand with WPF resources. And that is when a resource instance is actually created.

When is an instance of the resource created?

A resource instance is not created at declaration. It’s created at first use. To prove that, I created this simple TrueVisibilityConverter :

And declared it in App.xaml:

When placing a breakpoint in the Converter’s constructor and launching the application, the breakpoint isn’t hit. It was hit only When adding usage of it in MainWindow.cs.

Now that we got that out of the way, let’s answer some questions and see some numbers.

Question 1: Is splitting resources in App.xaml to many Merged Dictionaries file vs. one long App.xaml file means longer application startup time?

As we just saw, declaring resources in App.xaml doesn’t do much unless we use those resources. So for a correct benchmark we need to use a bunch of resources in MainWindow.

Benchmark 1:

  1. Create a lot of different resources in App.xaml (I used ControlTemplates showing icon drawings)
  2. Use the resources In MainWindow to make sure they are created.
  3. Measure load time from App constructor until MainWindow was loaded
Benchmark 2:

  • Create a lot of resource dictionary files and place the resources from the previous benchmark in the new files
  • In App.xaml, merge all the new dictionaries:
Results:

1 – All in one long file (Avg,): 2 – With merged dictionaries (Avg,):
236 milliseconds 241 milliseconds

Conclusion:
This benchmark is hard to check since it’s hard to mock as much resources as you’d have in an actual application. So this benchmark is inconclusive in a way. However, I feel pretty confidently that spreading your resources to many merged dictionaries won’t hurt the startup time much and is insignificant.

Question 2: Is loading all resources in App.xaml once better than loading the resources every time with merged dictionary?

It makes sense that loading resources in App.xaml once should be faster, since with merged dictionaries a new instance of the resource is created every time. The question is, how significant is this to application’s life cycle?

WPF has to do a lot of things behind the scenes – Measure, Render, create Control classes, etc. It’s quite possible loading resources is insignificant.

Benchmark 1 – Everything in App.xaml:

  1. Created two simple resources in App.xaml: A converter and a ControlTemplate with an icon
2. Create a simple UserControl that uses these resource
3. On the click of a button, add 500 of these babies to MainWindow
4. Measure the loading time of the last MySquare and print it
Like all benchmarks here, I ran this about 10 times and got average time.

Benchmark 2 – Use Merged Dictionaries:

  1. Instead of having the resources in App.xaml, create a new Resource Dictionary – Dictionary.xaml
2. Now, add this resource dictionary in MySquare.xaml
3. Create and add MySquare to StackPanel 500 times and measure the time span (same as in previous benchmark)

The results:

Resources in App.xaml (Avg,): Resources in merged dictionary (Avg,):
299 milliseconds 495 milliseconds

Conclusion:
The difference is significant. However keep in mind that this is a 200 milliseconds difference here and we are creating 500 user controls. Each of these has to merge dictionaries and create instances of the resources.
So my conclusion here is not to use merged dictionaries in controls that are created many times or controls that are resource-heavy and created more than once. In fact, since resources are created at first use, why not have everything in App.xaml or in a resource dictionary merged into App.xaml?

Question 3: Is DynamicResource instead of StaticResource an issue? How big of an issue?

I used here the same benchmark as before, and ran it twice. MySquare.xaml now looked like this:

Note that the ContentControl’s Template is now with DynamicResource.

The results:

Resources in
App.xaml
+ StaticResource:
Resources in
merged dictionary
+ StaticResource:
Resources in
App.xaml
DynamicResource:
Resources in
merged dictionary
DynamicResource:
299 milliseconds 495 milliseconds  306 milliseconds  552 milliseconds

Conclusion:
WPF probably does sort of caching for DynamicResource because we see that when the resource is in App.xaml, the difference is only 7 milliseconds, even though we supposedly have to look for the resource 500 times.
When we used merged dictionaries, the difference was pretty significant, but I think bare-able.

It’s reasonable to assume that when we have a big application, a new screen / control has enough resources to be equivalent to the 500 resources we are using here. So using DynamicResource will actually add 50 milliseconds to its load time. 50 milliseconds is not that much noticeable for user experience, but when added up, it can make some difference.

Another thing to consider is Memory

When we declare a resource in application scope in App.xaml, the instance is created at first use and never garbage collected. It stays in memory forever for further use.

On the other hand, when declaring a resource in some Control’s resources, or in the Control using Merged Dictionaries, the resource will be garbage collected when the control is unloaded.

So if you have a memory-heavy resource that is rarely used in the application, it makes sense not to declare it in App.xaml.

Summary

I think understanding resources when working on a large application is critical. Resources can seriously affect your application’s load time and performance.

We also saw that there isn’t always a right and wrong answer here. I’d say declare everything in App.xaml and use it as StaticResource, except that there is a memory factor to consider.

So here are some rule of thumb conclusions:

  • Prefer StaticResource to DynamicResource
  • If you’re creating a Control a lot of times, declare the resources in App.xaml for re-usability. Otherwise, new instances will be created each time which will impact performance.
  • If you’re using a resource rarely and it’s memory-heavy, prefer to user merged dictionaries instead of declaring it in application scope (App.xaml)
  • In a small application and even medium sized, using DynamicResource and merged dictionaries inappropriately probably won’t make a noticeable difference.
    However, these small and medium applications tend to grow into large monsters and it will be much harder to refactor a large monster.

 

Have a great day everyone.
And don’t forget to share, like and comment if you liked the post!

One thought on “WPF XAML Resource Benchmark

  1. Pingback: WPF Merged Dictionary problems and solutions - Michael's Coding Spot

Leave a Reply