During the past year, we’ve found and fixed a lot of perf issues in Expression and WPF. I’d like to relate a few of them, not so much because you’ll have the exact same problems, but that the pattern of finding and resolving the bugs may be helpful experiences. To start:
Expression uses a tree data structure to keep track of the XAML source code. Each node in the tree has a property called Children that returns a List of all its child nodes. For leaf nodes this collection was always empty, but even so a new collection object was always allocated. In some scenarios, this resulted in megabytes of allocations. To fix this, we implemented a singleton EmptyList class. Leaf nodes always return the same instance of this collection, removing all the allocation costs.
There are two implementation patterns here. The simplest is to have a static EmptyList, like this:
public static List EmptyList = new List();
and just always return that. This will get you most of the performance you want. We went a little further and implemented a whole class, giving us greater correctness and even slightly better perf. Here for example is the implementation of the ICollection members on EmptyList:
public void Add(T item)
{
throw new NotSupportedException();
}
public void Clear()
{
}
public bool Contains(T item)
{
return false;
}
public void CopyTo(T[] array, int arrayIndex)
{
}
public int Count
{
get { return 0; }
}
public bool IsReadOnly
{
get { return true; }
}
public bool Remove(T item)
{
return false;
}
In general, collection classes are a good place for teams to look at optimization: Expression, WPF and other Microsoft teams have all implemented specialized collections for degenerate cases and other cases where the BCL collections are overly general or expensive.