.NET programming tips and solution

General Considerations1. Resource CleanupFailing to clean up resources is a common cause of performance and scalabilitybottlenecks. Review your code to make sure all resources are closed and released assoon as possible. This is particularly important for shared and limited resources such asconnections. Make sure your code calls Dispose (or Close) on disposable resources.Make sure your code uses finally blocks or using statements to ensure resources areclosed even in the event of an exception. 2. ExceptionsWhile structured exception handling is encouraged because it leads to more robustcode and code that is less complex to maintain than code that uses method returncodes to handle error conditions, exceptions can be expensive. Make sure you do notuse exception handling to control regular application flow. Use it only for exceptionalconditions. Avoid exception handling inside loops — surround the loop with atry/catch block instead if that is required. Also identify code that swallows exceptionsor inefficient code that catches, wraps, and rethrows exceptions for no valid reason.

3. String ManagementExcessive string concatenation results in many unnecessary allocations, creating extrawork for the garbage collector. Use StringBuilder for complex string manipulations andwhen you need to concatenate strings multiple times. If you know the number ofappends and concatenate strings in a single statement or operation, prefer the +operator. In ASP.NET applications, consider emitting HTML output by using multipleResponse.Write calls instead of using a StringBuilder.

4. Threading:Server-side code should generally use the common language runtime (CLR) threadpool and should not create threads on a per-request basis. Review your code to ensurethat appropriate use is made of the thread pool and that the appropriatesynchronization primitives are used. Make sure your code does not lock whole classesor whole methods when locking a few lines of code might be appropriate. Also makesure your code does not terminate or pause threads by using Thread.Abort orThread.Suspend.

5. BoxingBoxing causes a heap allocation and a memory copy operation. Review your code toidentify areas where implicit boxing occurs. Pay particular attention to code insideloops where the boxing overhead quickly adds up. Avoid passing value types inmethod parameters that expect a reference type. Sometimes this is unavoidable. InCheck List for Improving the Performance of .NET Applicationsthis case, to reduce the boxing overhead, box your variable once and keep an objectreference to the boxed copy as long as needed, and then unbox it when you need avalue type again. Excessive boxing often occurs where you use collections that storeSystem.Object types. Consider using an array or a custom-typed collection classinstead. To identify locations that might have boxing overhead, you can search yourassembly’s Microsoft intermediate language (MSIL) code for the box and unboxinstructions, using the following command line.Ildasm.exe yourcomponent.dll /text findstr boxIldasm.exe yourcomponent.dll /text findstr unboxTo measure the overhead, use a profiler.Checklist for Managed Code Performance1. Design Considerations1.1. Design for efficient resource management.1.2. Reduce boundary crossings.1.3. Prefer single large assemblies rather than multiple smaller assemblies.1.4. Factor code by logical layers.1.5. Treat threads as a shared resource.1.6. Design for efficient exception management.2. Class Design Considerations2.1. Do not make classes thread safe by default.2.2. Consider using the sealed keyword.2.3. Consider the tradeoffs of using virtual members.2.4. Consider using overloaded methods.2.5. Consider overriding the Equals method for value types.2.6. Know the cost of accessing a property.2.7. Consider private versus public member variables.2.8. Limit the use of volatile fields.3. Garbage Collection Guidelines3.1. Identify and analyze your application’s allocation profile.3.2. Avoid calling GC.Collect.3.3. Consider weak references with cached data.3.4. Prevent the promotion of short-lived objects.3.5. Set unneeded member variables to Null before making long-running calls.3.6. Minimize hidden allocations.3.7. Avoid or minimize complex object graphs.3.8. Avoid preallocating and chunking memory.4. Finalize and Dispose4.1. Call Close or Dispose on objects that support it.4.2. Use the using statement in Microsoft® C# and Try/Finally blocks in MicrosoftVisual4.3. Basic®.NET to ensure Dispose is called.4.4. Do not implement Finalize unless required.4.5. Implement Finalize only if you hold unmanaged resources across client calls.4.6. Move the finalization burden to the leaves of object graphs.4.7. If you implement Finalize, implement IDisposable.4.8. If you implement Finalize and Dispose, use the Dispose pattern.4.9. Suppress finalization in your Dispose method.4.10. Allow Dispose to be called multiple times.4.11. Call Dispose on base classes and on IDisposable members.4.12. Keep finalizer code simple to prevent blocking.4.13. Provide thread-safe cleanup code only if your type is thread-safe.5. Pinning5.1. If you need to pin buffers, allocate them at startup.6. Threading6.1. Minimize thread creation.6.2. Use the thread pool when you need threads.6.3. Use a Timer to schedule periodic tasks.6.4. Consider parallel versus synchronous tasks.6.5. Do not use Thread.Abort to terminate other threads.6.6. Do not use Thread.Suspend and Thread.Resume to pause threads.7. Asynchronous Calls7.1. Consider client-side asynchronous calls for UI responsiveness.7.2. Use asynchronous methods on the server for I/O bound operations.7.3. Avoid asynchronous calls that do not add parallelism.8. Locking and Synchronization8.1. Determine if you need synchronization.8.2. Determine the approach.8.3. Determine the scope of your approach.8.4. Acquire locks late and release them early.8.5. Avoid locking and synchronization unless required.8.6. Use granular locks to reduce contention.8.7. Avoid excessive fine-grained locks.8.8. Avoid making thread safety the default for your type.8.9. Use the fine grained lock (C#) statement instead of Synchronized.8.10. Avoid locking “this”.8.11. Coordinate multiple readers and single writers by using ReaderWriterLockinstead of lock.8.12. Do not lock the type of the objects to provide synchronized access.9. Boxing and Unboxing9.1. Avoid frequent boxing and unboxing overhead.9.2. Measure boxing overhead.9.3. Use DirectCast in your Visual Basic .NET code.10. Exception Management10.1. Do not use exceptions to control application flow.10.2. Use validation code to avoid unnecessary exceptions.10.3. Use the finally block to ensure resources are released.10.4. Replace Visual Basic .NET On Error Goto code with exception handling.10.5. Do not catch exceptions that you cannot handle.10.6. Be aware that rethrowing is expensive.10.7. Preserve as much diagnostic information as possible in your exceptionhandlers.10.8. Use performance monitor to monitor common language runtime (CLR)exceptions.11. Iterating and Looping11.1. Avoid repetitive field or property access.11.2. Optimize or avoid expensive operations within loops.11.3. Copy frequently called code into the loop.11.4. Consider replacing recursion with looping.11.5. Use for instead of foreach in performance-critical code paths.12. String Operations12.1. Avoid inefficient string concatenation.12.2. Use + when the number of appends is known.12.3. Use StringBuilder when the number of appends is unknown.12.4. Treat StringBuilder as an accumulator.12.5. Use the overloaded Compare method for case-insensitive string comparisons.13. Arrays13.1. Prefer arrays to collections unless you need functionality.13.2. Use strongly typed arrays.13.3. Use jagged arrays instead of multidimensional arrays.14. Collections14.1. Analyze your requirements before choosing the collection type.14.2. Initialize collections to the right size when you can.14.3. Consider enumerating overhead.14.4. Prefer to implement IEnumerable with optimistic concurrency.14.5. Consider boxing overhead.14.6. Consider for instead of foreach.14.7. Implement strongly typed collections to prevent casting overhead.14.8. Be efficient with data in collections.15. Reflection and Late Binding15.1. Prefer early binding and explicit types rather than reflection.15.2. Avoid late binding.15.3. Avoid using System.Object in performance critical code paths.15.4. Enable Option Explicit and Option Strict in Visual Basic.NET.16. Code Access Security16.1. Consider SuppressUnmanagedCodeSecurity for performance-critical, trustedscenarios.16.2. Prefer declarative demands rather than imperative demands.16.3. Consider using link demands rather than full demands for performance -critical, trusted scenarios.17. Working Set Considerations17.1. Load only the assemblies you need.17.2. Consider assemblies that are being loaded as side effects.17.3. Reduce the number of application domains, and/or make assemblies sharedassemblies.17.4. Reduce the number of threads.Checklist for ADO.NET Performance18. Design Considerations18.1. Design your data access layer based on how the data is used.18.2. Cache data to avoid unnecessary work.18.3. Connect by using service accounts.18.4. Acquire late, release early.18.5. Close disposable resources.18.6. Reduce round trips.18.7. Return only the data you need.18.8. Use Windows authentication.18.9. Choose the appropriate transaction type.18.10. Use stored procedures.18.11. Prioritize performance, maintainability, and productivity when you choosehow to pass data across layers.18.12. Consider how to handle exceptions.18.13. Use appropriate normalization.19. Microsoft® .NET Framework Data Providers19.1. Use System.Data.SqlClient for Microsoft SQL Server™ 7.0 and later.19.2. Use System.Data.OleDb for SQL Server 6.5 or OLE DB providers.19.3. Use System.Data.ODBC for ODBC data sources.19.4. Use System.Data.OracleClient for Oracle.19.5. Use SQLXML managed classes for XML data and SQL Server 2000.20. Connections20.1. Open and close the connection in the method.20.2. Explicitly close connections.20.3. When using DataReaders, specify CommandBehavior.CloseConnection.20.4. Do not explicitly open a connection if you use Fill or Update for a singleoperation.20.5. Avoid checking the State property of OleDbConnection.20.6. Pool connections.21. Commands21.1. Validate SQL input and use Parameter objects.21.2. Retrieve only the columns and rows you need.21.3. Support paging over large result sets.21.4. Batch SQL statements to reduce round trips.21.5. Use ExecuteNonQuery for commands that do not return data.21.6. Use ExecuteScalar to return single values.21.7. Use CommandBehavior.SequentialAccess for very wide rows or for rows withbinary large21.8. objects (BLOBs).21.9. Do not use CommandBuilder at run time.22. Stored Procedures22.1. Use stored procedures.22.2. Use CommandType.Text with OleDbCommand.22.3. Use CommandType.StoredProcedure with SqlCommand.22.4. Consider using Command.Prepare.22.5. Use output parameters where possible.22.6. Consider SET NOCOUNT ON for SQL Server.23. Parameters23.1. Use the Parameters collection when you call a stored procedure.23.2. Use the Parameters collection when you build SQL statements.23.3. Explicitly create stored procedure parameters.23.4. Specify parameter types.23.5. Cache stored procedure SqlParameter objects.24. DataReader24.1. Close DataReader objects.24.2. Consider using CommandBehavior.CloseConnection to close connections.24.3. Cancel pending data.24.4. Consider using CommandBehavior.SequentialAccess with ExecuteReader.24.5. Use GetOrdinal when using an index-based lookup.25. DataSet25.1. Reduce serialization.25.2. Use primary keys and Rows.Find for indexed searching.25.3. Use a DataView for repetitive non-primary key searches.25.4. Use the optimistic concurrency model for datasets.25.5. XML and DataSet Objects25.6. Do not infer schemas at run time.25.7. Perform bulk updates and inserts by using OpenXML.26. Types26.1. Avoid unnecessary type conversions.27. Exception Management27.1. Use the ConnectionState property.27.2. Use try/finally to clean up resources.27.3. Use specific handlers to catch specific exceptions.28. Transactions28.1. Use SQL transactions for server controlled-transactions on a single data store.28.2. Use ADO.NET transactions for client-controlled transactions on a single datastore.28.3. Use Distributed Transaction Coordinators (DTC) for transactions that spanmultiple data stores.28.4. Keep transactions as short as possible.28.5. Use the appropriate isolation level.28.6. Avoid code that can lead to deadlock.28.7. Set the connection string Enlist property to false.29. Binary Large Objects29.1. Use CommandBehavior.SequentialAccess and GetBytes to read data.29.2. Use READTEXT to read from SQL Server 2000.29.3. Use OracleLob.Read to read from Oracle databases.29.4. Use UpdateText to write to SQL Server databases.29.5. Use OracleLob.Write to write to Oracle databases.29.6. Avoid moving binary large objects repeatedly.

1 Responses to Check List for Improving the Performance of .NET Applications