Tag Archives: performance

How to measure rendering time in a WPF application ?

Last week, a colleague of mine asked me an interesting question: “I’m filling a control with content and I’d like to measure the time needed to render my control. How can I do that ?”

The first approach is to measure the elapsed time needed to instantiate and populate the control from C# code. We can use the StopWatch class to have a precise and easy to use measuring tool.

Stopwatch sw = new Stopwatch();
sw.Start();

for (int i = 0; i < 5000; i++)
{
  // here is the operation that fills the control
  this.canvas.Children.Add(new Rectangle());
}

sw.Stop();
MessageBox.Show("Took " + sw.ElapsedMilliseconds + " ms");

However this approach will not give good results because we're not taking into account the time needed to render elements in the visual tree. This is because elements are not rendered when you call the Add methods (for example in a Canvas) but when the visual tree is fully loaded.

A much better approach is to use the Dispatcher and request it to process an action at a priority right bellow the Render priority which is the Loaded priority:

dispatcherpriority

Using this trick, we ensure that all rendering actions have been completed. We can use the following code to do that:

Stopwatch sw = new Stopwatch();
sw.Start();

for (int i = 0; i < 5000; i++)
{
  // here is the operation that fills the control
  this.canvas.Children.Add(new Rectangle());
}

this.Dispatcher.BeginInvoke(
  DispatcherPriority.Loaded,
  new Action(() =>
  {
    sw.Stop();
    MessageBox.Show("Took " + sw.ElapsedMilliseconds + " ms");
  }));

Hope this helps !

The cost of building Visual Trees

In the current project I’m working on, I’m designing a diagramming component. Of course because it’s for work I can’t release the source code (however if you want a good starting point you can check out this article). Designing such a component is a challenging task and there are a number of things I learned during the last few months that I’m glad to share here.

As you problably know the WPF engine manages 2 trees: the logical tree and the visual tree. For each logical item (that you declare in the XAML), the item is expanded with its visual tree (for example, a scrollbar is made of RepeatButtons and a Thumb). To visualize the visual tree you can use a tool like snoop.

In a diagramming tool, you might want to draw lines betweeen entities, like the following:

connection

In this article, we’re going to talk about the underlying control that we can use to do that. If you need to create that kind of control, you basically have 2 options:

  • inherits from Control and override the OnRender method to do the basic graphic operations (such as drawing a line or an ellipse)
  • inherits from Control and create a ControlTemplate to fill the visual tree of your control

Of course the first option has better performance, but it’s also less evolutive. Moreover, in the OnRender method, you can only do low level graphic operations.

Using the second option is generally fine and easy:

  1. create the class that inherit from Control
  2. create a style that targets your new control
  3. add a Setter to set the ControlTemplate property
  4. fill the ControlTemplate’s content

Here is a sample ControlTemplate for a basic connection (assuming that the Connection class has 4 double dependency properties (X1,Y1) (X2,Y2) that defines that start and the end point):


Of course this is a very minimal template, you’re probable going to improve it by adding new features:

  • 2 rectangles to show the extremities of the connection
  • 2 thumb to be able to drag’n’drop the extremities
  • 1 context menu to access connection’s operations

You can do that by adding more controls to the template. Now, take a second and think about the performances. Time is needed to built and render the visual tree and the most complex it is, the longer it takes. I did a quick benchmark on my machine and here are the results for 500 connections added in a Canvas:

performance

What we can see is that adding only 5 controls in the template, we multiply the rendering time by 4 ! That means we must be careful when we’re designing ControlTemplate that are going to be instantiated many time. Before creating the control we should think about whether the control is going to by displayed 1, 10, 100 or 1000 times in our application. More complex ControlTemplates mean more time to render them. Several techniques can be used to improved performance:

  • use a panel that supports UI virtualization (such a VirtualizingStackPanel)
  • use adorners to give feedback while an item is selected to improve creation performance (create the Adorner only when the item is selected)

To explore other performance related techniques: