We are starting a new series of articles that will mostly be geared towards the development minded of our readers. This new series details how to optimize and improve the performance of your .NET applications. In this series we will discuss how to approach performance in your application, explain performance considerations, and how to engineer for performance during the life-cycle of your application.
We will organize this series in the following sections:
· Application engineering and design considerations
· Measuring and tuning performance
The information we provide in this series will help you build applications that perform well and meet the various performance objectives, such as; response time, throughput, CPU utilization, memory utilization, and disk and network I/O. We’ll provide information how to measure and monitor and tune your application by using the appropriate configuration. We will also provide a number of principles and best practices that help improve performance.
Important to remember is that you set performance objectives upfront that include workload, response time, resource utilization, and throughput. Settings these objectives upfront helps the decision making process during the design phase of your application and it helps you to evaluate the performance of your application.
If you define your objectives well, it gives you a handle on where to focus during design and development phases. Performance metrics are used to measure the various scenarios of your application and when you compare them to your objectives to determine if your performance goals are met.
.NET Performance Best Practices At a Glance
We’ll start with discussing best practices at a glance to give an idea what topics we’ll be discussing in this series.
Design Best Practices
· When you consider performance, balance your requirements with other service attributes of your application such as security and maintenance
· Model performance starting in the early stages of the design process to evaluate the objectives against your design decisions. This can save time and resources down the road.
· When it comes to deployment of your application, take into consideration any corporate policies and procedures as well as the infrastructure that your application is being deployed on. Identifying these requirements helps selecting the appropriate architecture and resolve possible conflicts between your application and infrastructure architecture early on.
· Prioritize performance, maintenance, and ease of development when selecting a particular development approach. For example, you can using structures eliminates the need to implement your own serialization. XML is great for interoperability and flexibility, however, it is quite verbose and can require a huge parsing effort. In addition, XML can be used to transport large amounts of data, so use a DataReader to render the data quickly, but do not pass a DataReader object between application layers.
· If you are designing distributed applications, prefer a service oriented approach above an object oriented approach.
.NET Development Best Practices
The following items list at a glance how to improve the performance of managed code.
· Use FxCop.exe to analyse your binary assemblies and double check they conform to the .NET design guidelines recommended by Microsoft.
· Evaluate your object classes design and look at performance issues associated with class properties and implications of class inheritance.
· Manage memory efficiently by writing code that helps the garbage collector to function efficiently. You can accomplish this by minimizing hidden allocations and avoid promotion of short-lived objects, pre-allocating memory, chunking memory, and forcing garbage collections.
· Try to avoid creating threads on a per-request basis, or using Thread.Abort or Thread.Suspend.
· Avoid making asynchronous calls if they do not add parallelism and that block the thread right after initiating the call. In those situations, there is no benefit of using asynchronous calls.
· Clean up your resources as soon as you have finished using them. For example, use finally blocks in exception handling, or use Dispose on any disposable objects.
· Try to use StringBuilder when creating complex string manipulations and concatenating strings multiple times.
These are a few of the best development practices. We’ll discuss all of them in detail in a follow-up article. Let’s list a few data access performance best practices.
Data Access Performance
· Use database connection pooling to share connections across different requests
· Allow the user to page through large results sets when delivering large result sets to the end user one page at a time. DataAdapter and DataGrid are appropriate for small amounts of data. For large result sets use the SQL SELECT TOP statement to restrict the size of a result set.
· Try to stay away from moving binary large object data repeatedly, but consider storing pointers in the database to file locations instead of the binary object itself.
· If you can use a DataReader object instead of a DataSet object, do so, but use DataReader only if you need read-only access to data and do not have a requirement to cache the data. Use DataSet when you need the added flexibility or want to cache data between different requests.
· Optimize long running queries by using SQL profiler, and to identify the cause of the long-running query use SQL analyzer. ‘
Improving ASP.NET performance
· Optimize your web pages by trimming the size of each page and reduce the number of graphics. Disable view state for pages that don’t require this. Make sure buffering is enabled to reduce the communication between client and server.
· Tune your ASP.NET thread pool. We’ll provide details on how to this in a follow-up article.
· Utilize the Cache API to cache your data, either by using output caching or by partial page fragment caching. To do this effectively, separate the static and dynamic areas of your pages and user controls.
· Disable session state if you don’t need it. If you do need it choose the appropriate method from the in-process store, the out-of-process state servers, or SQL server. Generally, the in-process store offers the best performance. Use the ReadOnly attribute on pages that only read the session state.
Improving .NET remoting performance
· If you use remoting reduce the number of round trips of communication by using chunky interface.
· Serialize only the data that you need to improve serialization performance by using the NonSerialized attribute preventing unnecessary fields from being serialized.
· Use the following methods to improve serialization efficiency:
– Use column name aliasing to reduce the size of column names
– Avoid serializing the original and new values for DataSet field if not needed
– Only serialize those DataTable instances that you require
Improving Interop Performance
· To reduce marshaling costs, consider he amount and type of data you pass to and from unmanaged code.
· Avoid unnecessary marshaling by using explicit In and Out attributes
· You can minimize heap fragmentation by not pinning objects longer than the duration of a P/Invoke call. If you have a fairly heavily loaded server application, consider calling the Marshal.ReleaseComObject function to make sure your COM objects are released in a timely manner.
As you can see there are a lot of items to be taken into consideration if you want to improve the performance of your .NET application. Over the next few weeks we will go deeper into the topics that we touched on in this introduction.