a Grape Solutions-ről
és megoldásaink
referenciák, partnerek
nyitott pozícióink
elérhetőségeink

Silverlight performance optimization part #1

Pfliegel Bálint2010.02.25. 09:01

I'm currently working on the second edition of Pluto - with a lot more focus on performance optimization, looking at the audio engine and UI both. I put together couple of points I found interesting.

If you played Neverhood, you already know that 'bad is always where you forget to look'. This is exactly the case here and there are a lot of places to look for.

 

Basic stuff

First you need to be familiar with Silverlight's rendering engine and base concepts to optimize UI performance and setup a development environment which allows you to visualize problems and measure your optimizations. 

This means to look for isWindowless, MaxFrameRate, visibility vs opacity and these sort of things, there are numerous articles describing how to do it. Seema Ramchandani gave insightful presentations on the topic, here is a link for the mix09 one. MaxFrameRate helps a lot if you don't have rich visual media.

 

UI optimization

If you do UI optimization take care of the following:

 

Styles and controls: Check the default styles and create your own minimizing the usage of animations, gradient brushes and vsm - generally minimize everything that costs CPU and you don't need. In case of a complex control, you might also doubt what it does internally - you could also create your own at any time :) Silverlight default style is really beautiful - but quite resource hungry. In case of a simple ScrollBar control (with no code behind actions), giving it an optimized style could bring down the CPU from 20% to 8% (in case of moving the thumb like a madman).

There are two great articles for control development I could recommend:

http://msdn.microsoft.com/en-us/magazine/cc721611.aspx

http://blogs.silverlight.net/blogs/jesseliberty/archive/2008/09/12/digging-into-custom-controls.aspx

 

Lot of objects: In Pluto's songplan there could be cases to draw 1000+ rectangles or lines at 20fps - which I implemented in the first version using Silverlight primitives. Despite the SL team did an outstanding job on the UI engine - these cases require to develop a custom control and use for instance WriteableBitmap (and WriteableBitmapEx from codeplex) with optimizations for the specific special case.

 

Redraw only what you need: Redraw and invalidate only what you need. If you have a visual update every 50ms, check if your controls visually really changed - and touch their properties only in that case. EnableRedrawRegions could help a lot with this task. Also check how huge is the area you redraw - likely redrawing only the portions you need will help much. I wonder what should one do if the area IS large and you need to redraw the WHOLE area (scrolling). Hmm.

 

Text animation: Never forget TextHintingMode, when you have animated (or even frequently updated, fixed position) text, this simple hint helps your CPU a lot: http://weblogs.asp.net/gavinleader/archive/2009/09/25/animating-text-in-silverlight.aspx

 

Numerical calculations


Data types: Double is generally around 3.5 more expensive than float or int (which is pretty much the same speed).

 

Sin/Cos/etc: Beware, costy. Also, don't try to create your own replacement using a lookup table, you just can't beat it.

 

Number of arguments: There is not much of a difference if you do a*b or a*b*c*d. I did not dig into the reasons (should be low level registers and stuff), just empirical.

 

Big and small: Avoid arithmetic operations with very small (1.0E-10 and below) and very large (Infinity, hmm) numbers - you'll have a very high CPU penalty if you do so. If you spend a couple of CPU cycles to check your values for cases like that, you would be better off in the end.

 

Pixel shaders: Those guys are REALLY fast. I had the thought to implement synth part calculations of the new Pluto as pixel shaders (maybe the idea could be applied in other cases), see for yourself: http://kodierer.blogspot.com/2009/08/silverlight-3-writeablebitmap.html

Also I found a couple of blog posts saying it's not a feasible approach (limited registers, cannot read output, etc).

 

General optimization

Thread creation: Thread creation is REALLY expensive, if you create 100 threads in a second, your CPU will be around 15% for nothing. Always reuse threads, it requires just some simple planning.

 

Object creation: Frequent object creation (500+/second) is also expensive (but a lot less than thread creation) - especially if you count the GC. GC.Collect is ofcourse not an option. Try to pool your objects and reuse them.

 

Method calls: Minimize method calls - but maintain your code structure. Tradeoff. Did not encounter many cases where this was the root cause.

 

Visual Studio build - 'optimize code' checkbox: Check it. In case of Pluto, it helped around 30%. Also, despite there is no explicit inline modifier in .Net, the JIT complier (not VS) does inline the method in certain cases. http://www.ademiller.com/blogs/tech/2008/08/c-inline-methods-and-optimization/

 

And generally: check if your code is optimal. In case you could spare another CPU cycle - do it and it will add up pretty soon. 2-3% extra CPU is not a big deal - but if you have around 10 such cases, you could gain 25%, which is a lot. 

Nincsenek hozzászólások.

Szólj hozzá!

Név: *
Url:
E-mail:
Címkefelhő
bdd (1) browser (1) egyéb (2) entity framework (1) linq (1) linq2sql (1) sales (1) test (1) welcome (1) windows (1)