Click here to Skip to main content
15,879,239 members
Articles / Desktop Programming / WPF

Dependency Property Performance and Lissajous Figures

Rate me:
Please Sign up or sign in to vote.
4.93/5 (8 votes)
2 Jun 2009CPOL3 min read 19.2K   11  
A simple lesson regarding the speed of dependency properties ... and a funky Oscilloscope!
oscilloscope.jpg

View the above Silverlight application on my blog.

A few nights ago, I was working on a Silverlight control which renders some quite complex Paths, the geometry of which is determined from a number of dependency properties. In order to gain UI coolness points, I wanted to animate the dependency properties in order to see a smooth transition of the Path geometry between the old and new values. The animation itself was easy to implement, but the resultant animation was distinctly choppy.

Now, I cannot share the code of the Silverlight control I was working on, so I have decided to illustrate the point via a Lissajous Figure. These curves are plotted using the following simple formula:

Image 2

A simple Lissajous figure can be constructed by creating a UserControl which dependency properties for the various parameters in the above equations. The control contains a single path whose Data property will be set to a suitable geometry in code behind, and a ‘container’ element for our path which we use to determine the width / height of our curve.

XML
<UserControl ...>
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid x:Name="PathContainer" Margin="5">            
            <Path x:Name="lissajousFigure" Stroke="#9EFFFF" StrokeThickness="1"/>
        </Grid>
    </Grid>
</UserControl>

The points that are used to construct the geometry are calculated from the ActualXFrequency, ActualYFrequency, ActualPhase properties of our user control, together with the ActualWidth and ActualHeight of the container in order to scale the curve appropriately.

C#
for(double t = 0; t < Math.PI * 10; t += Math.PI / 36)
{
    points.Add(new Point()
    {
        X = PathContainer.ActualWidth * Math.Sin(t * ActualXFrequency) / 2
            + ActualWidth / 2,
        Y = PathContainer.ActualHeight * Math.Cos(t * ActualYFrequency + ActualPhase) / 2
            + PathContainer.ActualHeight / 2
    });
}

When I was investigating the choppy animation performance in my Silverlight control, I concentrated initially on other parts of the application; the construction of the paths, the property changed events and the resultant chain reaction of event which can result in a spiders-web of method invocations. It was not until a little later that I focused on the code that constructed the geometry, which looks not too dissimilar to the above.

At first sight, the code looks just fine, we are performing a number of simple operations on a few simple properties. However, this is not the case, these properties are not simple CLR properties backed by value or reference types. These are Dependency Properties, which are much more complex beasts!

A quick change to the above code to ensure that the DP accessors are called only once, rather than 360 times, resulted in code which ran ~400 times faster!

C#
double actualWidth = PathContainer.ActualWidth;
double actualHeight = PathContainer.ActualHeight;
double actualXFrequency = ActualXFrequency;
double actualPhase = ActualPhase;
double actualYFrequency = ActualYFrequency;
 
for(double t = 0; t < Math.PI * 10; t += Math.PI / 36)
{
    points.Add(new Point()
    {
        X = actualWidth * Math.Sin(t * actualXFrequency) / 2
            + actualWidth / 2,
        Y = actualHeight * Math.Cos(t * actualYFrequency + actualPhase) / 2
            + actualHeight / 2
    });
}

When you think about the features that the DP framework provides (databinding, animation, inheritance, etc …), it is not at all surprising that this is at some performance cost. And I will forgive the reader if they tell me that I am stating the obvious! However, in code behind, where DPs are accessed via their CLR wrappers, it is easy to forget this. It should also be noted that DPs are far from slow. It is only when they are used as part of a complex iterative calculations that the performance-hit will be felt.

Anyhow, this is a small lesson in what is possibly obvious! However, I must admit, I had far too much fun creating the Lissajous Figure example application as you can see from the app at the start of this article … it takes me back to Physics lab at University!

A few other points of interest:

  • The code uses ElementName binding attached behaviour I created in an earlier blog post. As a result, there is no code-behind in the main page (I may be flirting with Silverlight but my WPF credibility remains intact!)
  • The various dependency properties for the Lissajous Figure user control are defined using T4 templates as described in this CodeProject article.

I also really like the way that when one of the DPs such as Phase is updated, a storyboard is used to animate the accompanying ActualPhase DP to the updated value.

C#
partial void OnPhasePropertyChanged(DependencyPropertyChangedEventArgs e)
{
    AnimateProperty("ActualPhase", Phase, 100);
}
 
private void AnimateProperty(string propertyName, double targetValue, int milliseconds)
{
    Storyboard sb = new Storyboard();
 
    DoubleAnimation b = new DoubleAnimation() { To = targetValue };
    b.Duration = new Duration(new TimeSpan(0, 0, 0, 0, milliseconds));
    sb.Children.Add(b);
    Storyboard.SetTarget(b, this);
    Storyboard.SetTargetProperty(b, new PropertyPath("(" + propertyName + ")"));
 
    sb.Begin();
}

This means that even though the slider controls bound to the DPs move in discrete steps, the above animation gives the illusion of the steps being continuous.

You can download the full project source: silverlightdpperformance.zip.

[Oscilloscope image reproduced from Wikipedia under Creative Commons Licence.]

Regards, Colin E.

This article was originally posted at http://www.scottlogic.co.uk/blog/wpf?p=317

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Scott Logic
United Kingdom United Kingdom
I am CTO at ShinobiControls, a team of iOS developers who are carefully crafting iOS charts, grids and controls for making your applications awesome.

I am a Technical Architect for Visiblox which have developed the world's fastest WPF / Silverlight and WP7 charts.

I am also a Technical Evangelist at Scott Logic, a provider of bespoke financial software and consultancy for the retail and investment banking, stockbroking, asset management and hedge fund communities.

Visit my blog - Colin Eberhardt's Adventures in .NET.

Follow me on Twitter - @ColinEberhardt

-

Comments and Discussions

 
-- There are no messages in this forum --