Tuesday, June 8, 2010

.NET and WPF optimization guidelines

WPF optimization issues

Classes with unmanaged objects
Example of unmanaged objects
  • DB connections
  • File handles
Only classes that has unmanaged objects should contain a finalizer method (the equivalent of a destructor in C++), and such classes must implement the IDisposable interface. use the class.Dispose when you finish with the object and the Dispose method should clean up all the unmanaged resources.

Class Abc : IDisposable {
private bool m_disposed = false;
public void Dispose() {
Dispose(true);
GC.SupressFinalize(this); //prevent calling the finalizer if dispose has specifically been
// called
}
private void Dispose(bool calledByUser) {
if(!m_disposed) {
if(calledByUser) {
//can clean up other managed objects
}
// clean up the UNMANGED resources here
m_disposed = true;
}
}
~Abc() {
Dispose(false);
}
}

Strings and StringBuilder
Adding strings using + creates multiple objects, so StringBuilder is better, but on the other hand, string builder has its downsides in terms of being a heavy object to manage. The general rule given is that for one line concatenation with a known number of strings use:

StrSum = st1 + st2 + st3

If it is inside a loop then use StringBuilder


References
Do not keep references to short lived objects in long lived ones because this will prevent them from being garbage collected.

Threading and timers
Timers are much lighter weight than timers, so whenever possible use Timers rather than Threads.
(look into the subjects of Thread Pools)

Arrays and Collections
Whenever possible use Arrays rather than collections

Properties
Properties also have overhead. If it is a simple get and set, the compiler will probably optimize them to an equivalent of an inline functions, but if not, then there is some overhead in using them, so when you can use the original object use it rather than the property that refers to it, or when in loops read the value outside the loop and use it inside the loop.

Class inheritance (seal and override)
Use virtual functions only when you actually override the functions
Seal functions with the override keyword to enable optimization.
ex: override sealed public void fun1()

Things that prevent classes from being freed
There are a number of things that prevents objects from being garbage collected even if they seem to us that they are not references anymore. Among these cases are:

1- with event handlers

When we add an event handler to an object

obj1.clicked += obj2.clickEventHandler

obj1 will keep a reference to obj2, so even when we are done with using obj2, it will not be garbage collected until we unsubscribe

obj1.clicked -= obj2.clickEventHandler
or

obj1.clicked = null;

2 - With Freezable objects
Refer to the section on freezable below

Freezables
Examples of freezable classes:
  • Brush
  • Pen
  • Geometry
  • Transform
  • AnimationTimeline
  • ImageSource
Some characteristic of Freezable classes are
  • A frozen object CAN be shared across threads, while unfrozen cannot
  • A Freezable (but unfrozen) object provide change notifications when a sub-property value changes. This means that a freezable object will maintain a reference to the object that uses it in order be able to send it change notifications and hence prevent it from being garbage collected (see the above section, 'things that prevent classes from being freezed'). To overcome this we must either freeze the freezable object, or assign the reference in the object using this freezable object to null.

Button myButton = new Button(); SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);            if (myBrush.CanFreeze) {     // Makes the brush unmodifiable.     myBrush.Freeze(); }  myButton.Background = myBrush;  
// or instead of freezing myBrush
myButton.Background = null;

  • It is not possible to freeze a freezable if:
- it has animated or data bound poperty
  - it has properties that are set by dynamic resources
  - it contains freezable sub-objects that cannot be frozen

To freeze an object in the XAML code
first add the following name spaces at the beginning
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions"
//then
'<'SolidColorBrush       
 x:Key="MyBrush"       
PresentationOptions:Freeze="True"        
Color="Red" '/>'