Do You Use
Multidimensional Arrays?
If your code uses
multidimensional arrays, see if you can replace the code with a jagged array (a
single dimensional array of arrays) to benefit from MSIL performance
optimizations.
Note Jagged arrays are
not CLS compliant and may not be used across languages.
Do You Use Strongly
Typed Arrays?
Identify places in
your code where you use object arrays (arrays containing the Object
type). If you use object arrays to store other types, such as integers or
floats, the values are boxed when you add them to the array. Use a strongly
typed array instead, to avoid the boxing. For example, use the following to
store integers.
int[] arrIn = new
int[10];
Use the preceding to
store integers instead of the following.
Object[] arrObj =
new Object[10];
Do You Call EndInvoke
After Calling BeginInvoke?
Review your code to
see where it calls BeginInvoke to use asynchronous delegates. For each
call to BeginInvoke, make sure your code calls EndInvoke to avoid
resource leaks.
Do You Poll for
Asynchronous Invocation Results?
Avoid polling for
asynchronous invocation results. Polling is inefficient and uses precious
processor cycles which can be used by other server threads. Use a blocking call
instead. Methods of AsyncResult.AsyncWaitHandle.WaitHandle
class such as WaitOne, WaitAll, and WaitAny are good
examples of blocking calls.
Do You Call Unmanaged
Code?
When calling
unmanaged code, you can remove the runtime security checks by using the
SuppressUnmanagedCodeSecurity attribute. This converts the check to a
LinkDemand check, which is much faster. However, you should only do so if
you are absolutely certain that your code is not subject to luring attacks.
Do You Use Declarative
Security?
Where
possible, it is recommended that you use declarative security instead of
imperative security checks. The current implementation of demand provides better
performance and support with the security tools that are currently being built
to help security audits.
Note that
if your security checks are conditional within a method, imperative security is
your only option.
Do You Review Your
Code for Performance issues?
During your
code reviews, pay particular attention to the following areas:
· Frequent code
paths. Prioritize your
code review process by identifying code paths that are frequently executed and
begin your review process in these areas.
· Frequent
loops. Even the slightest
inefficiency inside a loop is magnified many times over depending on the number
of iterations. Specifically watch out for repetitive property access inside your
loops, using foreach instead of for, performing expensive
operations within your loops, and using recursion. Recursion incurs the overhead
of having to repeatedly build new stack frames.
There are a
few areas that regularly lead to performance bottlenecks. Start your code review
by looking for the following common performance issues:
· Resource
cleanup
· Exceptions
· String
management
· Threading
· Boxing
Resource
Cleanup
Failing to
clean up resources is a common cause of performance and scalability bottlenecks.
Review your code to make sure all resources are closed and released as soon as
possible. This is particularly important for shared and limited resources such
as connections. Make sure your code calls Dispose (or Close) on
disposable resources. Make sure your code uses finally blocks or
using statements to ensure resources are closed even in the event of an
exception.
Exceptions
While
structured exception handling is encouraged because it leads to more robust code
and code that is less complex to maintain than code that uses method return
codes to handle error conditions, exceptions can be expensive.
Make sure
you do not use exception handling to control regular application flow. Use it
only for exceptional conditions. Avoid exception handling inside loops —
surround the loop with a try/catch block instead if that is required.
Also identify code that swallows exceptions or inefficient code that catches,
wraps, and rethrows exceptions for no valid reason.
String
Management
Excessive
string concatenation results in many unnecessary allocations, creating extra
work for the garbage collector. Use StringBuilder for complex string
manipulations and when you need to concatenate strings multiple times. If you
know the number of appends and concatenate strings in a single statement or
operation, prefer the + operator. In ASP.NET applications, consider
emitting HTML output by using multiple Response.Write calls instead of
using a StringBuilder.
Threading
Server-side
code should generally use the common language runtime (CLR) thread pool and
should not create threads on a per-request basis. Review your code to ensure
that appropriate use is made of the thread pool and that the appropriate
synchronization primitives are used. Make sure your code does not lock whole
classes or whole methods when locking a few lines of code might be appropriate.
Also make sure your code does not terminate or pause threads by using
Thread.Abort or Thread.Suspend.
Boxing
Boxing
causes a heap allocation and a memory copy operation. Review your code to
identify areas where implicit boxing occurs. Pay particular attention to code
inside loops where the boxing overhead quickly adds up. Avoid passing value
types in method parameters that expect a reference type. Sometimes this is
unavoidable. In this case, to reduce the boxing overhead, box your variable once
and keep an object reference to the boxed copy as long as needed, and then unbox
it when you need a value type again.
Excessive
boxing often occurs where you use collections that store System.Object
types. Consider using an array or a custom-typed collection class instead.
To identify
locations that might have boxing overhead, you can search your assembly's
Microsoft intermediate language (MSIL) code for the box and unbox
instructions, using the following command line.
Ildasm.exe yourcomponent.dll /text | findstr box Ildasm.exe yourcomponent.dll /text | findstr unbox
To measure
the overhead, use a profiler.