.NET Framework 2.0 Performance Guidelines
From Guidance Share
- J.D. Meier, Srinath Vasireddy, Ashish Babbar, Rico Mariani, and Alex Mackman
[edit]
What's New in 2.0
- Use TryParse Method to Avoid Unnecessary Exceptions
- Use Token Handle Resolution API to get the Metadata for Reflection
- Use Generics to Eliminate Cost of Boxing, Casting and Virtual calls
- Use GC.AddMemoryPressure while consuming Unmanaged Objects through COM Interop
- Use Promotable Transactions while Working with SQL Server 2005
- Use HandleCollector API while Managing Expensive Unmanaged Resource Handles
- Use ExcludeSchema Serialization Mode while Exchanging Typed DataSet Over Network
- Consider Using Hard Binding and String Freezing in Advanced NGEN Scenario
- Use Workstation GC for Managing Multiple Server Processes on a Single Server Machine
- Load Assemblies As Domain Neutral In Multiple Domain Scenarios
- Choose An Appropriate Base Address For Optimum Performance From NGEN
- Use ReadAllLines, ReadAllText, ReadAllBytes Methods for Simple Reading of an Entire File
- Use NGEN for Faster Application Startup and for Ability to Share Assemblies
- Use NeutralResourcesLanguageAttribute Class to Avoid Extra Lookups for the Specified Culture
- Set UseGlobalLock to False for Lock Free Tracing
- Use UtcNow for DateTime Comparison and Calculations
- Consider Using Precompiled Or Inline Regular Expressions
[edit]
Arrays
- Prefer arrays to collections unless you need functionality
- Use strongly typed arrays
- Use jagged arrays instead of multidimensional arrays
[edit]
Asynchronous
- Consider client-side asynchronous calls for UI responsiveness
- Use asynchronous methods on the server for I/O bound operations
- Avoid asynchronous calls that do not add parallelism
[edit]
Boxing and Unboxing
- Avoid frequent boxing and unboxing overhead
- Measure boxing overhead
- Use DirectCast in your Visual Basic .NET code
[edit]
Code Access Security
- Consider SuppressUnmanagedCodeSecurity for performance-critical trusted scenarios
- Prefer declarative demands rather than imperative demands
- Consider using link demands rather than full demands for performance-critical, trusted scenarios
[edit]
Collections
- Analyze your requirements before choosing the collection type
- Initialize collections to the right size when you can
- Consider enumerating overhead
- Prefer to implement IEnumerable with optimistic concurrency
- Consider boxing overhead
- Consider for instead of foreach
- Implement strongly typed collections to prevent casting overhead
- Be efficient with data in collections
[edit]
Exception Management
- Do not use exceptions to control application flow
- Use validation code to avoid unnecessary exceptions
- Use the finally block to ensure resources are released
- Replace Visual Basic .NET On Error Goto code with exception handling
- Do not catch exceptions that you cannot handle
- Be aware that rethrowing is expensive
- Preserve as much diagnostic information as possible in your exception handlers
- Use Performance Monitor to monitor CLR exceptions
[edit]
Finalize and Dispose
- Call Close or Dispose on classes that support it
- Use the using statement in C# and Try/Finally blocks in Visual Basic .NET to ensure Dispose is called
- Do not implement Finalize unless required
- Implement Finalize only if you hold unmanaged resources across client calls
- Move the Finalization burden to the leaves of object graphs
- If you implement Finalize, implement IDisposable
- If you implement Finalize and Dispose, use the Dispose pattern
- Suppress finalization in your Dispose method
- Allow Dispose to be called multiple times
- Call Dispose on base classes and on IDisposable members
- Keep finalizer code simple to prevent blocking
- Provide thread safe cleanup code only if your type is thread safe
[edit]
Garbage Collection
- Identify and analyze your application's allocation profile
- Avoid calling GC.Collect
- Consider weak references with cached data
- Prevent the promotion of short-lived objects
- Set unneeded member variables to Null before making long-running calls
- Minimize hidden allocations
- Avoid or minimize complex object graphs
- Avoid preallocating and chunking memory
[edit]
Iterating and Looping
- Avoid repetitive field or property access
- Optimize or avoid expensive operations within loops
- Copy frequently called code into the loop
- Consider replacing recursion with looping
- Use for instead of foreach in performance-critical code paths
[edit]
Locking and Synchronization
- Acquire locks late and release them early
- Avoid locking and synchronization unless required
- Use granular locks to reduce contention
- Avoid excessive fine-grained locks
- Avoid making thread safety the default for your type
- Use the fine-grained lock (C#) statement instead of Synchronized
- Avoid locking 'this'
- Coordinate multiple readers and single writers by using ReaderWriterLock instead of lock
- Do not lock the type of the objects to provide synchronized access
[edit]
Ngen.exe
- Scenarios where startup time is paramount should consider Ngen.exe for their startup path
- Scenarios which will benefit from the ability to share assemblies should adopt Ngen.exe
- Scenarios with limited or no sharing should not use Ngen.exe
- Consider Ngen.exe for ASP.NET version 2.0
- Measure performance with and without Ngen.exe
- Regenerate your image when you ship new versions
- Choose an appropriate base address
[edit]
Pinning
[edit]
Reflection and Late Binding
- Prefer early binding and explicit types rather than reflection
- Avoid late binding
- Avoid using System.Object in performance critical code paths
- Enable Option Explicit and Option Strict in Visual Basic .NET
[edit]
String Operations
- Avoid inefficient string concatenation
- Use + when the number of appends is known
- Use StringBuilder when the number of appends is unknown
- Treat StringBuilder as an accumulator
- Use the overloaded Compare method for case insensitive string comparisons
[edit]