This document discusses performance tuning of .NET applications. It begins by defining performance tuning as improving system performance. It then discusses identifying bottlenecks through profiling, such as by using dotTrace and dotMemory tools. Various ways to optimize performance are covered, such as choosing appropriate collections, making applications parallel as needed, and managing memory efficiently by reducing allocation and using value types and IDisposable patterns. The document aims to provide guidance on optimizing .NET applications through measurement and profiling.
6. Where is the Bottleneck?
for (int n = 2; n < 10000; ++n)
{
bool prime = true;
for (int d = 2; d < n; ++d)
{
if (n % d == 0)
{
prime = false;
break;
}
}
if (prime) Console.WriteLine(n);
}
10. How does it work?
1. Select Application to Profile
2. Start Profiling
3. Collect Data and Detect Bottlenecks
4. Optimize Performance
5. Compare Profiling Results
6. Repeat Until Desired Results (Or
Possible)
13. Dozens of Builtin Collections
✓ List<T>
✓ ArrayList<T>
✓ Dictionary<K,V>
✓ HashSet<T>
✓ Queue<T>
✓ SortedList<K,V>
✓ SortedDictionary<K,V>
✓ SortedSet<T>
✓ Stack<T>
… and more
14. Choose Proper Collection
■ Stop using List<T> for everything
■ Ask yourself:
Do you need to access each element by index?
For zero-based index: Use ArrayList and StringCollection classes and
the List<T> generic class.
For key based index: The Hashtable, SortedList, ListDictionary, and
StringDictionary classes, and the Dictionary<TKey, TValue> and
SortedDictionary<TKey, TValue> generic classes.
Do you need to sort your collection?
The Hashtable class sorts its elements by their hash codes.
The SortedDictionary<TKey, TValue> and SortedList<TKey, TValue> generic
classes sort their elements by the key.
15. Collection - (Contd.)
Do you need to search your collection?
ListDictionary is faster than Hashtable for small collections
(10 items or fewer).
The Dictionary<TKey, TValue> generic class provides faster
lookup than the SortedDictionary<TKey, TValue> generic class.
The multi-threaded implementation is
ConcurrentDictionary<TKey, TValue>. ConcurrentBag<T>
provides fast multi-threaded insertion for unordered data.
Do you need collections that accept only strings?
StringCollection (based on IList) and StringDictionary
(based on IDictionary).
16. Collection Ordering
Direct
Access?
Lookup
Efficiency
Manipulate
Efficiency
Notes
Dictionary Unordered Via Key Key: O(1) O(1) Best for high performance lookups.
SortedDictionary Sorted Via Key Key: O(log n) O(log n)
Compromise of Dictionary speed and
ordering, uses binary search tree.
List Unordered Via Index
Index: O(1)
Value: O(n)
O(n)
Best for smaller lists where direct
access required and no sorting.
SortedList Sorted Via Key Key: O(log n) O(n)
Faster lookup on preloaded data, but
slower loads.
LinkedList Unordered No Key: O(n) O(1)
Best for lists where inserting/deleting in
middle is common and no direct access
required.
HashSet Unordered Via Key Key: O(1) O(1)
Unique unordered collection, like a
Dictionary except key and value are
same object.
21. GC as a Performance Problem
■ The .NET GC is non-deterministic
✓ Contributes unexpecteds, potentially very
long delays that destroy responsiveness.
✓ No way to anticipate the delay or react to
it.
22. There’s no GC if you don’t allocate.
Reducing allocation is key to
reducing GC costs.
23. Reducing Allocation
✓ Use value types
✓ Pool large objects (such as buffers)
✓ Avoid allocation large temporary objects
24. Use IDisposable
✓ Finalize is expensive.
✓ Dispose the object that is not needed.
✓ GC does not call Dispose() for you. It’s
your duty to call it.