Wednesday, January 30, 2008

Code Review

I usually need to have information like this at hand. This is the compilation of techniques to improve General Performance in manage code. This information belong to Microsoft Patterns and Practices and can be found in the MSDN Library. It’s good to know that every Pattern and Practices have its correspondent Checklist which is super useful to verify quickly what we have not checked yet.

Design Considerations:

Design for efficient resource management.
Reduce boundary crossings.
Prefer single large assemblies rather than multiple smaller assemblies.
Factor code by logical layers.
Treat threads as a shared resource.
Design for efficient exception management.

Class Design Considerations:

Do not make classes thread safe by default.
Consider using the sealed keyword.
Consider the tradeoffs of using virtual members.
Consider using overloaded methods.
Consider overriding the Equals method for value types.
Know the cost of accessing a property.
Consider private versus public member variables.
Limit the use of volatile fields.

Garbage Collection Guidelines

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.
Finalize and Dispose Call Close or Dispose on objects that support it.
Use the using statement in Microsoft® C# and Try/Finally blocks in Microsoft 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.
If you need to pin buffers, allocate them at startup.


Minimize thread creation.
Use the thread pool when you need threads.
Use a Timer to schedule periodic tasks.
Consider parallel versus synchronous tasks.
Do not use Thread.Abort to terminate other threads.
Do not use Thread.Suspend and Thread.
Resume to pause threads.
Asynchronous Calls
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.

Locking and Synchronization

Determine if you need synchronization.
Determine the approach.
Determine the scope of your approach.
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.

Boxing and Unboxing

Avoid frequent boxing and unboxing overhead.
Measure boxing overhead. Use DirectCast in your Visual Basic .NET code.

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 common language runtime (CLR) exceptions.

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.

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.


Prefer arrays to collections unless you need functionality.
Use strongly typed arrays.
Use jagged arrays instead of multidimensional arrays.


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.

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.

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.

Working Set Considerations

Load only the assemblies you need.
Consider assemblies that are being loaded as side effects.
Reduce the number of application domains, and/or make assemblies shared assemblies.
Reduce the number of threads.

Native Image Generator (Ngen.exe)

Scenarios where startup time is paramount should consider Ngen.exe for their startup path. Scenarios that will benefit from the ability to share assemblies should adopt Ngen.exe.
Scenarios with limited or no sharing should not use Ngen.exe.
Do not use Ngen.exe for ASP.NET version 1.0 and 1.1. 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. Install assemblies in the GAC if you want to use NGEN to get the best performance.
A setup application for an update of a library assembly should run the 'Ngen.exe update' command.

No comments: