Click here to Skip to main content
Click here to Skip to main content

ASP.NET Best Practices for High Performance Applications

, 21 Mar 2006
Rate this:
Please Sign up or sign in to vote.
This article lists the techniques that you can use to maximize the performance of your ASP.NET applications. It provides common issues, design guidelines, and coding tips to build optimal and robust solutions.

Introduction

ASP.NET is much more powerful than classic ASP, however it is important to understand how to use that power to build highly efficient, reliable and robust applications. In this article, I tried to highlight the key tips you can use to maximize the performance of your ASP.NET pages. The list can be much longer, I am only emphasizing the most important ones.

1. Plan and research before you develop

Research and investigate how .NET can really benefit you. .NET offers a variety of solutions on each level of application design and development. It is imperative that you understand your situation and pros and cons of each approach supported by this rich development environment. Visual Studio is a comprehensive development package and offers many options to implement the same logic. It is really important that you examine each option and find the best optimal solution suited for the task at hand. Use layering to logically partition your application logic into presentation, business, and data access layers. It will not only help you create maintainable code, but also permits you to monitor and optimize the performance of each layer separately. A clear logical separation also offers more choices for scaling your application. Try to reduce the amount of code in your code-behind files to improve maintenance and scalability.

2. String concatenation

If not handled properly, String Concatenation can really decrease the performance of your application. You can concatenate strings in two ways.

  • First, by using string and adding the new string to an existing string. However, this operation is really expensive (especially if you are concatenating the string within a loop). When you add a string to an existing string, the Framework copies both the existing and new data to the memory, deletes the existing string, and reads data in a new string. This operation can be very time consuming and costly in lengthy string concatenation operations.
  • The second and better way to concatenate strings is using the StringBuilder Class. Below is an example of both approaches. If you are considering doing any type of String Concatenation, please do yourself a favor and test both routines separately. You may be surprised at the results.

    'Concatenation using String Class 
    Response.Write("<b>String Class</b>")
    Dim str As String = ""
    Dim startTime As DateTime = DateTime.Now
    Response.Write(("<br>Start time:" + startTime.ToString()))
    Dim i As Integer
    For i = 0 To 99999
    str += i.ToString()
    Next i
    Dim EndTime As DateTime = DateTime.Now
    Response.Write(("<br>End time:" + EndTime.ToString()))
    Response.Write(("<br># of time Concatenated: " + i.ToString))

    Results: Took 4 minutes and 23 Seconds to to complete 100,000 Concatenations.

    String Class
    • Start time: 2/15/2006 10:21:24 AM
    • End time: 2/15/2006 10:25:47 AM
    • # of time Concatenated: 100000

    'Concatenation using StringBuilder
     Response.Write("<b>StringBuilder Class</b>")
     Dim strbuilder As New StringBuilder()
     Dim startTime As DateTime = DateTime.Now
     Response.Write(("<br>Start time:" + startTime.ToString()))
     Dim i As Integer
     For i = 0 To 99999
     strbuilder.Append(i.ToString())
     Next i
     Dim EndTime As DateTime = DateTime.Now
     Response.Write(("<br>Stop time:" + EndTime.ToString()))
     Response.Write(("<br># of time Concatenated: " + i.ToString))

    Results: Took less than a Second to complete 100,000 Concatenations.

    StringBuilder Class
    • Start time: 2/15/2006 10:31:22 AM
    • Stop time:2/15/2006 10:31:22 AM
    • # of time Concatenated: 100000

This is one of the many situations in which ASP.NET provides extremely high performance benefits over classic ASP.

3. Avoid round trips to the server

You can avoid needless round trips to the Web Server using the following tips:

  • Implement Ajax UI whenever possible. The idea is to avoid full page refresh and only update the portion of the page that needs to be changed. I think Scott's article gave great information on how to implement Ajax Atlas and <atlas:updatepanel> control.
  • Use Client Side Scripts. Client site validation can help reduce round trips that are required to process user's request. In ASP.NET you can also use client side controls to validate user input.
  • Use Page.ISPostBack property to ensure that you only perform page initialization logic when a page is loaded the first time and not in response to client postbacks.

    If Not IsPostBack Then 
    LoadJScripts()
    End If
  • In some situations performing postback event handling are unnecessary. You can use client callbacks to read data from the server instead of performing a full round trip. Click here for details.

4. Save viewstate only when necessary

ViewState is used primarily by Server controls to retain state only on pages that post data back to themselves. The information is passed to the client and read back in a hidden variable. ViewState is an unnecessary overhead for pages that do not need it. As the ViewState grows larger, it affects the performance of garbage collection. You can optimize the way your application uses ViewState by following these tips:

Situation when you don't need ViewState

ViewState is turned on in ASP.NET by default. You might not need ViewState because your page is output-only or because you explicitly reload data for each request. You do not need ViewState in the following situations:

  • Your page does not post back. If the page does not post information back to itself, if the page is only used for output, and if the page does not rely on response processing, you do not need ViewState.
  • You do not handle server control events. If your server controls do not handle events, and if your server controls have no dynamic or data bound property values, or they are set in code on every request, you do not need ViewState.
  • You repopulate controls with every page refresh. If you ignore old data, and if you repopulate the server control each time the page is refreshed, you do not need ViewState.

Disabling viewstate

There are several ways to disable ViewState at various levels:

  • To disable ViewState for a single control on a page, set the EnableViewState property of the control to false.
  • To disable ViewState for a single page, set the EnableViewState attribute in the @ Page directive to false. i.e.

    <%@ Page EnableViewState="false" %> 
  • To disable ViewState for a specific application, use the following element in the Web.config file of the application:

    <pages enableViewState="false" />
  • To disable ViewState for all applications on a Web server, configure the <pages> element in the Machine.config file as follows:

    <pages enableViewState="false" />

Determine the size of your ViewState

By enabling tracing for the page, you can monitor the ViewState size for each control. You can use this information to determine the optimal size of the ViewState or if there are controls in which the ViewState can be disabled.

5. Use session variables carefully

Avoid storing too much data in session variables, and make sure your session timeout is reasonable. This can use a significant amount of server memory. Keep in mind that data stored in session variables can hang out long after the user closes the browser. Too many session variables can bring the server on its knees. Disable session state, if you are not using session variables in the particular page or application.

  • To disable session state for a page, set the EnableSessionState attribute in the @ Page directive to false.i.e.

    <%@ Page EnableSessionState="false" %> 
  • If a page requires access to session variables but will not create or modify them, set the EnableSessionState attribute in the@ Page directive to ReadOnly. i.e.

    <%@ Page EnableSessionState="ReadOnly" %>   
  • To disable session state for a specific application, use the following element in the Web.config file of the application.

    <sessionState mode='Off'/>
  • To disable session state for all applications on your Web server, use the following element in the Machine.config file:

    <sessionState mode='Off'/>

6. Use Server.Transfer

Use the Server.Transfer method to redirect between pages in the same application. Using this method in a page, with Server.Transfer syntax, avoids unnecessary client-side redirection. Consider Using Server.Transfer Instead of Response.Redirect. However, you cannot always just replace Response.Redirect calls with Server.Transfer. If you need authentication and authorization checks during redirection, use Response.Redirect instead of Server.Transfer because the two mechanisms are not equivalent. When you use Response.Redirect, ensure you use the overloaded method that accepts a Boolean second parameter, and pass a value of false to ensure an internal exception is not raised. Also note that you can only use Server.Transfer to transfer control to pages in the same application. To transfer to pages in other applications, you must use Response.Redirect.

7. Use server controls when appropriate and avoid creating deeply nested controls

The HTTP protocol is stateless; however, server controls provide a rich programming model that manage state between page requests by using ViewState. However nothing comes for free, server controls require a fixed amount of processing to establish the control and all of its child controls. This makes server controls relatively expensive compared to HTML controls or possibly static text. When you do not need rich interaction, replace server controls with an inline representation of the user interface that you want to present. It is better to replace a server control if:

  • You do not need to retain state across postbacks
  • The data that appears in the control is static or control displays read-only data
  • You do not need programmatic access to the control on the server-side

Alternatives to server controls include simple rendering, HTML elements, inline Response.Write calls, and raw inline angle brackets (<% %>). It is essential to balance your tradeoffs. Avoid over optimization if the overhead is acceptable and if your application is within the limits of its performance objectives.

Deeply nested hierarchies of controls compound the cost of creating a server control and its child controls. Deeply nested hierarchies create extra processing that could be avoided by using a different design that uses inline controls, or by using a flatter hierarchy of server controls. This is especially important when you use controls such as Repeater, DataList, and DataGrid because they create additional child controls in the container.

8. Choose the data viewing control appropriate for your solution

Depending on how you choose to display data in a Web Forms page, there are often significant tradeoffs between convenience and performance. Always compare the pros and cons of controls before you use them in your application. For example, you can choose any of these three controls (DataGrid, DataList and Repeater) to display data, it's your job to find out which control will provide you maximum benefit. The DataGrid control can be a quick and easy way to display data, but it is frequently the most expensive in terms of performance. Rendering the data yourself by generating the appropriate HTML may work in some simple cases, but customization and browser targeting can quickly offset the extra work involved. A Repeater Web server control is a compromise between convenience and performance. It is efficient, customizable, and programmable.

9. Optimize code and exception handling

To optimize expensive loops, use For instead of ForEach in performance-critical code paths. Also do not rely on exceptions in your code and write code that avoids exceptions. Since exceptions cause performance to suffer significantly, you should never use them as a way to control normal program flow. If it is possible to detect in code a condition that would cause an exception, do so. Do not catch the exception itself before you handle that condition. Do not use exceptions to control logic. A database connection that fails to open is an exception but a user who mistypes his password is simply a condition that needs to be handled. Common scenarios include checking for null, assigning a value to a String that will be parsed into a numeric value, or checking for specific values before applying math operations. The following example demonstrates code that could cause an exception and code that tests for a condition. Both produce the same result.

'Unnecessary use of exception
 Try
     value = 100 / number
Catch ex As Exception
    value = 0
End Try

' Recommended code
If Not number = 0 Then
    value = 100 / number
Else
    value = 0
End If

Check for null values. If it is possible for an object to be null, check to make sure it is not null, rather then throwing an exception. This commonly occurs when you retrieve items from ViewState, session state, application state, or cache objects as well as query string and form field variables. For example, do not use the following code to access session state information.

'Unnecessary use of exception
Try
value = HttpContext.Current.Session("Value").ToString
Catch ex As Exception
Response.Redirect("Main.aspx", False)
End Try
 
'Recommended code 
If Not HttpContext.Current.Session("Value") Is Nothing Then
value = HttpContext.Current.Session("Value").ToString
Else
Response.Redirect("Main.aspx", False)
End If

10. Use a DataReader for fast and efficient data binding

Use a DataReader object if you do not need to cache data, if you are displaying read-only data, and if you need to load data into a control as quickly as possible. The DataReader is the optimum choice for retrieving read-only data in a forward-only manner. Loading the data into a DataSet object and then binding the DataSet to the control moves the data twice. This method also incurs the relatively significant expense of constructing a DataSet. In addition, when you use the DataReader, you can use the specialized type-specific methods to retrieve the data for better performance.

11. Use paging efficiently

Allowing users to request and retrieve more data than they can consume puts an unnecessary strain on your application resources. This unnecessary strain causes increased CPU utilization, increased memory consumption, and decreased response times. This is especially true for clients that have a slow connection speed. From a usability standpoint, most users do not want to see thousands of rows presented as a single unit. Implement a paging solution that retrieves only the desired data from the database and reduces back-end work on the database. You should optimize the number of rows returned by the Database Server to the middle-tier web-server. For more information read this article to implement paging at the Database level. If you are using SQL Server 2000, please also look at this article.

12. Explicitly Dispose or Close all the resources

To guarantee resources are cleaned up when an exception occurs, use a try/finally block. Close the resources in the finally clause. Using a try/finally block ensures that resources are disposed even if an exception occurs. Open your connection just before needing it, and close it as soon as you're done with it. Your motto should always be "get in, get/save data, get out." If you use different objects, make sure you call the Dispose method of the object or the Close method if one is provided. Failing to call Close or Dispose prolongs the life of the object in memory long after the client stops using it. This defers the cleanup and can contribute to memory pressure. Database connection and files are examples of shared resources that should be explicitly closed.

Try
_con.Open()
Catch ex As Exception
Throw ex
Finally
If Not _con Is Nothing Then
_con.Close()
End If
End Try

13. Disable tracing and debugging

Before you deploy your application, disable tracing and debugging. Tracing and debugging may cause performance issues. Tracing and debugging are not recommended while your application is running in production. You can disable tracing and debugging in the Machine.config and Web.config using the syntax below:

<configuration>
   <system.web>
      <trace enabled="false" pageOutput="false" />
      <compilation debug="false" />
   </system.web>
</configuration>

14. Precompile pages and disable AutoEventWireup

By precompiled pages, users do not have to experience the batch compile of your ASP.NET files; it will increase the performance that your users will experience.

In addition, setting the AutoEventWireup attribute to false in the Machine.config file means that the page will not match method names to events and hook them up (for example, Page_Load). If page developers want to use these events, they will need to override the methods in the base class (for example, they will need to override Page.OnLoad for the page load event instead of using a Page_Load method). If you disable AutoEventWireup, your pages will get a slight performance boost by leaving the event wiring to the page author instead of performing it automatically.

15. Use stored procedures and indexes

In most cases you can get an additional performance boost by using compiled stored procedures instead of ad hoc queries.

Make sure you index your tables, and choose your indexes wisely. Try using Index Tuning Wizard and have it report to you what it thinks the best candidates for indexes would be. You don't have to follow all of its suggestions, but it may reveal things about your structure or data that will help you choose more appropriate indexes.

  • In SQL Server Management Studio (SQL Server 2005), highlight your query. Now from the Query menu, click Analyze Query in Database Engine Tuning Advisor.
  • You can do something similar in SQL Server 2000 to run the index tuning wizard? In Query Analyzer, highlight your query. From the Query menu, click Index Tuning Wizard.

References

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Ali Khan (OKC)
Web Developer
United States United States
I work for Hertz Corporation as System Developer /Analyst and have exposure to various development environments, web applications, databases, along with information and project management techniques.

Comments and Discussions

 
GeneralMy vote of 4 Pinmemberamnk.info16-May-13 21:02 
GeneralMy vote of 5 PinmemberM.Shawamreh2-Apr-13 23:06 
GeneralMy vote of 5 PinmemberHariPrasad katakam21-Feb-13 0:12 
GeneralMy vote of 4 PinmemberEduardo Ceratti27-Nov-12 7:47 
GeneralMy vote of 5 PinmemberGerard Castelló Viader31-Oct-12 7:29 
GeneralMy vote of 5 Pinmemberrajyarr17-Dec-11 16:05 
Generalwell done for your article, It helped us alot, Thank you very much!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PinmemberAWERT123200311-Mar-08 3:19 
GeneralUsing Block - 12. Explicitly Dispose or Close all the resources Pinmemberrickstrand21-Feb-08 13:29 
GeneralException Handling PinmemberChris L9-Dec-07 6:24 
GeneralKikoz68 + BlackBerry PinmemberChipalino27-Nov-07 5:36 
GeneralRe: Kikoz68 + BlackBerry PinmemberAli Khan (OKC)8-Dec-07 12:37 
QuestionKikoz68 you have problem? PinmemberAMassani24-Nov-07 22:55 
QuestionKikoz68 you have problem? Pinmemberdsmportal22-Nov-07 4:05 
AnswerRe: Kikoz68 you have problem? PinmemberAlex_Mish22-Nov-07 6:26 
AnswerRe: Kikoz68 you have problem? PinmemberAli Khan (OKC)22-Nov-07 7:18 
GeneralRe: Kikoz68 you have problem? PinmemberJasonRT22-Nov-07 8:13 
AnswerRe: Kikoz68 you have problem? PinmemberRenat.R22-Nov-07 19:44 
GeneralRe: Kikoz68 you have problem? PinmemberRenat.R22-Nov-07 19:50 
GeneralWell... PinmemberKikoz6819-Nov-07 19:30 
GeneralRe: Well... PinmemberAli Khan (OKC)20-Nov-07 11:47 
GeneralRe: Well... PinmemberKikoz6820-Nov-07 19:21 
GeneralRe: Well... PinmemberAli Khan (OKC)21-Nov-07 5:39 
GeneralRe: Well... PinmemberKikoz6821-Nov-07 17:56 
"If you agree that exceptions are expensive then what are you arguing about". Did you actually read what people say about your stuff? Smile | :) I'm arguing about the fact that there are situations (and PLENTY OF THEM) when, even though exceptions have high priority of execution and can reserve some memory for a very short period of time, you should not take it as an iron rule because advantages they provide can be FAR greater than disadvantages. I even described one of those situations but you ignored it.
 
"this article only suggests Not raising exceptions when you can easily avoid them". Excuse me? "Do not rely on exceptions in your code and write code that avoids exceptions." Can you translate this into anything other than "don't use exceptions at all"? This is what actually forced me to post my initial comment. I've seen silly "tips" before but never with such an aplomb...
 
"why would you raise an exception when you can easily handle it." And you were questioning my education? These are 2 totally different things - raising an exception and handling it.
 
"I don’t understand what your point is". Yep, that's exactly the problem. See below, please.
 
"Your view clearly contradicts with most designers’/developers’ experience, and Microsoft’s own website" (this is a quote from your earlier comment).
 
Here is a shot of one fatal and ugly error I took not so long ago on "Microsoft's own website": http://64.20.34.90.com/error.jpg
Note that this is NOT some "non-important" site, this is The MSDN you refer to. Let me explain the image in details:
 
This is not browser's own default error page which it displays when resource is inaccessible (crap happens sometimes). It's the famous "red-and-yellow", solid indication that framework is up and running on that particular IIS and there is NO error handling WHATSOEVER. Not even a reference to a default error page in web.config. Such a lame. I'm not even going to discuss the error itself which shows the level of "experience" of all those "developers" you're talking about (no redundant maintenance service on the site of such importance when you have objects that expire??). You were referring to this site (and, obviously) its creators as a final judgment, correct? Notice, btw, that this is related to exceptions as well.
 
Here is another one: I was stupid enough to attend one of those MS "training seminars" for former Front Page users (you were referring to them as a good source of knowledge). We were supposed to get info on all new stuff in .NET 2.0. The guy on the stage was a full time MS employee. Introduction paper said that he was one of the top MS programmers in US Southeast (or something like that). Well, somehow we got into a discussion on page events and the guy was telling us (with also a great deal of aplomb - MS Programmer!) that it's simply impossible to cancel a post back on the client if the button was declared as a web control. I gave him a simple line (this.thatButton.Attributes["onclick"] = "return false;";). Amazingly, he was trying to convince me that this line will not work. I left that conference and never wasted my time on stuff like this ever since. It happened in MS building at Lakewood Pkwy, Roswell, GA 30076 (if you need details).
 
What I'm saying is that you should not blindly trust anything that comes from big names, even if this is MS. Every one should analyze documentation of objects of interest and think why sometimes things are not that straight forward as they appear. Ms is a huge organization, with all typical side effects. In general, I found that MS has only 3 teams that deserve a real unconditional respect for what they do: guys who develop C# compiler, guys who rule the Office development and SqlServer team. All other teams there that I'm aware of are very questionable in terms of their ability to develop a solid product from the ground up. Take the ASP.NET 2.0, for example. In my opinion, guys who came up with the idea of "web site project" (those APP_ folders and stuff) need to be fired yesterday. Programmers complained so much that MS had to release web application project, effectively rolling back the entire APP_ effort. Read about it here: http://west-wind.com/weblog/posts/5601.aspx
 
Also, I'm curious: why don't you answer my other questions about the rest of your "tips"? Common, have some guts!
 
I gave you an example of how I would handle certain situation in the context of whatever has been said previously, inviting you to give me your vision and how you would go about it. Instead, I'm getting "the value of professionalism, ethics, corporate culture". Corporate culture is of particular interest for me here. I bet you have a BlackBerry, jeans are a big "no no" in your office, you attend 2-3 pointless meetings a day with 5-6 PMs and button clickers (pardon - Quality Assurance Engineers) who would go on and on on something you don't really care about. And you're totally fine with it. Or am I wrong? Smile | :)
 
In conclusion: I don't add a fancy signature to my comments. I just call myself a programmer. Wois me if you need to know whom you're talking to.
GeneralRe: Well... PinmemberAli Khan (OKC)22-Nov-07 7:08 
GeneralRe: Well... PinmemberJasonRT22-Nov-07 8:10 
GeneralRe: Well... [modified] PinmemberDutchMafia4-Aug-08 11:32 
GeneralCorrection PinmemberKikoz6821-Nov-07 18:00 
GeneralRe: Correction PinmemberGreatThinker25-Nov-07 2:35 
GeneralTranslate in Portuguese PinmemberFabio Galante Mans18-Nov-07 3:47 
GeneralDatareader GetDateTime error PinmemberLeshia21-May-07 4:34 
GeneralRe: Datareader GetDateTime error Pinmemberdavidxavier197724-Nov-07 23:58 
Questioncan u please explain how to use datareader better with an example Pinmemberrama charan12-Feb-07 4:28 
Generalthank u very very much Pinmemberrama charan12-Feb-07 4:18 
GeneralStored procs [modified] PinmemberDanInManchester3-Jul-06 5:44 
GeneralUsing Viewstate to store objects for performance Pinmemberbenoityip16-Mar-06 18:54 
GeneralThanks for the feedback PinmemberAli Khan (OKC)15-Mar-06 12:07 
GeneralMore resources Pinmembertvidigal8-Mar-06 7:33 
GeneralRe: More resources PinprofessionalS.K.Tripathi8-Jul-14 21:02 
GeneralPostback's PinmemberDarrenKopp2-Mar-06 14:46 
GeneralCorrection PinmemberDarrenKopp2-Mar-06 14:21 
QuestionString concatenation? PinmemberMasjj2-Mar-06 11:26 
AnswerRe: String concatenation? Pinmemberronmichael18-Nov-07 5:16 
GeneralInaccuracies PinmemberShazam9992-Mar-06 8:48 
GeneralRe: Inaccuracies PinmemberR. Mark2-Mar-06 9:43 
GeneralRe: Inaccuracies PinmemberShazam9993-Mar-06 5:39 
GeneralRe: Inaccuracies PinmemberArch4ngel22-Mar-06 3:40 
GeneralRe: Inaccuracies PinmemberDarrenKopp2-Mar-06 14:16 
GeneralRe: Inaccuracies PinmemberShazam9993-Mar-06 5:44 
GeneralRe: Inaccuracies PinmemberDarrenKopp3-Mar-06 18:04 
GeneralRe: Inaccuracies PinmemberShazam9996-Mar-06 12:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141216.1 | Last Updated 21 Mar 2006
Article Copyright 2006 by Ali Khan (OKC)
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid