Performance Overview

Performance can be a key factor in a successful Web site or project. This topic provides guidelines for improving performance of a site as well as links to best practices documentation.

This topic contains:

  • Best Practices

  • Background

  • Code Examples

Best Practices

The following list provides links to resources on the Microsoft Web site that describe overall best practices for ASP.NET Web site performance.

Back to top

Background

The section lists techniques that you can use to help maximize the performance of ASP.NET Web applications. The guidelines are divided into the following sections:

  • Page and server control processing

  • State management

  • Data access

  • Web applications

  • Coding practices

Page and Server Control Processing

The following guidelines suggest ways to work with ASP.NET pages and controls efficiently.

  • Avoid unnecessary round trips to the server   In some situations, you can use ASP.NET AJAX and partial-page rendering to accomplish tasks in browser code without performing a full postback. For example, you can use ASP.NET AJAX features to validate user input in the browser before the input is submitted to the server. For more information, see ASP.NET AJAX Overview and Partial-Page Rendering Overview.

  • In general, if you do not have to relay information to the server to be verified or to be written to a data store, you can improve the page's performance (and therefore the user experience) by avoiding round trips to the server.

  • If you develop custom server controls, consider designing them to render client script for some of their functionality. This can significantly reduce the number of times that information is sent to the Web server. For more information, see Developing Custom ASP.NET Server Controls and Creating Custom Client Script by Using the Microsoft AJAX Library.

  • Use the Page object's IsPostBack property to avoid unnecessary processing   Avoid running code on each postback if it only has to run the first time the page is requested. You can test the IsPostBack property to conditionally execute code depending on whether the page is running in response to a server control event.

  • Leave buffering on unless you have a specific reason to turn it off   There is a significant performance cost for disabling buffering of ASP.NET Web pages. For more information, see the Buffer property.

  • Use the Transfer method of the Server object or use cross-page posting to redirect between ASP.NET pages in the same application   For more information, see Redirecting Users to Another Page.

State Management

The following guidelines suggest ways to make state management efficient.

  • Save server control view state only when it is required   View state enables server controls to repopulate property values on a round trip without requiring you to write code. However, view state affects performance and page size because it is passed to and from the server in a hidden form field. If you are binding a server control to data on every round trip, saved view state is not useful, because the control's values are replaced with new values during data binding. In that case, disabling view state saves processing time and reduces the size of the page.

    By default, view state is enabled for all server controls. To disable it for a control, set the control's EnableViewState property to false, as in the following example:

    <asp:datagrid EnableViewState="false" datasource="..." 
       runat="server"/>
    

    You can also disable view state for a page by using the @ Page directive, as shown in the following example:

    <%@ Page EnableViewState="false" %>
    

    This is useful when the page does not require postback processing.

    Note

    The EnableViewState attribute is also supported in the @ Control directive to specify whether view state is enabled for a user control.

    To analyze the size of view state for a page, enable tracing for the page by setting trace="true" in the @ Page directive. In the trace output, examine the Viewstate column of the Control Hierarchy table. For more information, see ASP.NET Tracing Overview.

  • Avoid using view state encryption unless you have to   View state encryption prevents users from reading view-state values in the hidden view-state form field. For example, you might encrypt view state if a page includes a GridView control that maintains an identifier field in the DataKeyNames property in order to coordinate updates to records. Because you do not want the identifier to be visible to users, you can encrypt view state. However, encryption has a constant performance cost for initialization, and it has an additional cost that depends on the size of view state that is being encrypted. Encryption is performed every time that the page is loaded. Therefore, the same performance effect occurs when the page is first requested and during every postback.

  • Disable session state when you are not using it   To disable session state for a page, set the EnableSessionState attribute in the @ Page directive to false, as in the following example:

    <%@ Page EnableSessionState="false" %>
    

    Note

    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.

    You can also disable session state for ASP.NET Web service methods. For more information, see ASP.NET Application Services Overview.

    To disable session state for an application, set the Mode attribute to Off in the SessionState section of the application's Web.config file, as in the following example:

    <sessionState mode="Off" />
    
  • Choose the appropriate session-state provider for your application   ASP.NET provides multiple ways to store session data for your application. These include in-process session state, out-of-process session state as a Windows service, and out-of-process session state in a SQL Server database. (You can also create a custom session state provider to store session data in a data store that you specify.) Each approach has advantages, but in-process session state is by far the fastest approach. If you are using session state only for small amounts of data in session state, use the in-process provider. Use out-of-process session state options if you scale your application across multiple processors or across multiple computers, or if you want to persist session data when a server or process is restarted. For more information, see ASP.NET Session State Overview.

Data Access

The following guidelines suggest ways to make data access in your application efficient.

  • Use SQL Server and stored procedures for data access   SQL Server is the recommended choice for data storage to create high-performance, scalable Web applications. When you use the managed SQL Server provider, you can get an additional performance boost by using compiled stored procedures wherever possible instead of using SQL commands. For information, see Configuring Parameters and Parameter Data Types (ADO.NET).

  • Use the SqlDataReader class for a fast forward-only data cursor   The SqlDataReader class creates a forward-only, read-only data stream that is retrieved from a SQL Server database. The SqlDataReader class uses the SQL Server native network data-transfer format to read data directly from a database connection. If practical, use the SqlDataReader class, because it offers better performance than the DataSet class. For example, when you bind a data control to the SqlDataSource control, you will achieve better performance if you set the DataSourceMode property to DataReader. (However, a data reader supports less functionality than DataSet mode.) The SqlDataReader class implements the IEnumerable interface, which enables you to bind server controls to it. For more information, see the SqlDataReader class and Accessing Data with ASP.NET.

  • Cache data and page output whenever possible   Use ASP.NET caching if pages or data do have to be dynamically computed for every page request. If possible, design pages and data requests for caching, especially for situations where you expect heavy traffic. By using the cache appropriately, you can improve the performance of your site more than by using any other feature of the .NET Framework.

    When you use ASP.NET caching, follow these guidelines. First, do not cache too many items, because each cached item requires server memory. For example, do not cache items that are easily recalculated or rarely used. Second, do not assign a short expiration time to cached items. Items that expire quickly can cause extra work for cleanup code and for the garbage collector. You can monitor the turnover in the cache that is caused by expiring items by using the Cache Total Turnover Rate performance counter that is associated with the ASP.NET Applications performance object. A high turnover rate can indicate a problem, especially when items are removed before they expire. (This situation is sometimes known as memory pressure.)

    For information about how to cache page output and data requests, see ASP.NET Caching Overview.

  • Use SQL cache dependency appropriately   For caching data from SQL Server, ASP.NET supports both table-based polling and query notification, depending on the version of SQL Server that you are using. Table-based polling is supported by all versions of SQL Server. In table-based polling, if any data in a table changes, all cache items that are dependent on the table are invalidated. This can cause unnecessary turnover in the cache. Table-based polling is not recommended for tables that have frequent changes. For example, table-based polling would be recommended for a catalog table that changes infrequently. It would not be recommended for an orders table that is updated frequently.

    Query notification is supported by SQL Server 2005 and later versions. Query notification uses SQL queries to detect changes in a targeted set of rows. This reduces the number of notifications that are sent when a table is changed. Query notification can provide better performance than table-based polling. However, it does not scale to thousands of queries.

    For more information about SQL cache dependency, see Walkthrough: Using ASP.NET Output Caching with SQL Server and Caching in ASP.NET with the SqlCacheDependency Class.

  • **Use data source paging and sorting instead of UI (user interface) paging and sorting   **The UI paging feature of data controls such as DetailsView and GridView can be used with any data source object that supports the ICollection interface. For each paging operation, the data control queries the data source for the whole data collection, selects the row or rows to display, and then discards the remaining data.

    If a data source control implements DataSourceView and if the CanPage property returns true, the data control uses data source paging instead of UI paging. In that case, the data control requests only the rows that are required for each page to be displayed. Therefore, data source paging is more efficient than UI paging. Among standard ASP.NET controls, only the ObjectDataSource and LinqDataSource data source control support data source paging. To enable data source paging for other data source controls, you can inherit from the data source control that you want to use and then modify its behavior.

  • **Use a Timestamp column for concurrency control with the LinqDataSource control   **If a SQL Server database table does not contain a Timestamp column (a SQL Server data type), the LinqDataSource control checks data concurrency by storing the original data values in the Web page. LINQ to SQL checks the original values against the database before it updates or deletes the data. This approach can create a large Web page if the data record contains many columns or large column values. It can also represent a security risk if the record contains data that you do not want to expose in the page. When a database table has a Timestamp column, the LinqDataSource control stores only the timestamp value for future comparisons. LINQ to SQL can check the consistency of the data by determining whether the original timestamp matches the current timestamp value in the table. For more information about timestamps, see timestamp (Transact-SQL) on the MSDN Web site.

  • **Balance the security benefit of event validation with its performance cost   **Controls that derive from the System.Web.UI.WebControls and System.Web.UI.HtmlControls classes can validate that an event originated from the user interface that was rendered by the control. This helps prevent the control from responding to spoofed event notification. For example, by using event validation, the DetailsView control can prevent a malicious user from making a Delete call (which is not inherently supported in the control) and manipulating the control into deleting data. Event validation has some performance cost. You can control event validation by using the EnableEventValidation configuration element and the RegisterForEventValidation method. The cost of validation depends on the number of controls on the page, and is in the range of a few percent.

    Security noteSecurity Note:

    It is strongly recommended that you do not disable event validation. Before you disable event validation, make sure that no postback could be constructed that would have an unintended effect on your application.

  • **Use SqlDataSource control caching, sorting, and filtering   **If the DataSourceMode property of the SqlDataSource control is set to DataSet, the SqlDataSource control can cache the result set from a query. The SqlDataSource control's filtering and sorting operations can then use the cached data. An application can run faster if you cache the whole dataset and if you use the FilterExpression and SortParameterName properties to sort and filter. The data source control can then avoid making SQL queries with Where and Sort By clauses to access the database every time that users sort or filter data in the UI.

Web Applications

The following guidelines suggest ways to make Web applications as a whole work efficiently.

  • Precompile the site   A Web application is batch-compiled upon the first request for a resource such as an ASP.NET Web page. If no page in the application has been compiled, batch compilation compiles all pages in a directory in chunks to improve disk and memory usage. You can use the ASP.NET Compilation Tool (Aspnet_compiler.exe) to precompile a Web application. For in-place compilation, the compilation tool calls the ASP.NET runtime to compile the site the same way as when a user requests a page from the Web site. You can precompile a Web application so that the UI markup is preserved, or precompile the pages so that source code cannot be changed. For more information, see How to: Precompile ASP.NET Web Sites.

  • Disable debug mode   Always disable debug mode before you deploy a production application or conduct any performance measurements. If debug mode is enabled, the performance of your application can be decreased. For information about how to set debug mode, see Editing ASP.NET Configuration Files.

  • Tune the configuration files for the Web server computer and for specific applications   The default configuration for ASP.NET enables the widest set of features and the most common scenarios. You can change some default configuration settings in order to improve the performance of your applications, depending on the features that you use. The following list includes configuration changes that you should consider:

    • Enable authentication only for applications that need it   By default, the authentication mode for ASP.NET applications is Windows, or integrated NTLM. In most cases it is best to disable authentication in the Machine.config file and enable it in the Web.config files only for applications that need it.

    • Configure your application to the appropriate request and response encoding settings   The ASP.NET default encoding is UTF-8. If your application uses only ASCII characters, configure your application for ASCII for a small performance improvement.

    • Disable AutoEventWireup for your application   Setting the AutoEventWireup attribute to false in the Web.config file prevents the page from binding page events to methods based on a name match (for example, Page_Load). This gives pages a small performance boost. To handle page events, use one of two strategies. The first strategy is to override the methods. For example, you can override the OnLoad method of the Page object to write code for the page load event. (Make sure that you call the base method to make sure that all events are raised.) The second strategy is to bind to page events by using the Handles keyword in Visual Basic or by using delegate wire-up in C#.

    • Remove unused modules from the request-processing pipeline   By default, all features are left active in the HttpModules node in the Web server computer's Machine.config file. Depending on which features your application uses, you can remove unused modules from the request pipeline to obtain a small performance boost. Review each module and its functionality and customize it to your needs. For example, if you do not use session state and output caching in your application, you can remove the modules for these features from the HttpModules list.

  • Run Web applications out-of-process on Internet Information Services 5.0   By default, ASP.NET on IIS 5.0 will service requests by using an out-of-process worker process. This feature has been tuned for fast throughput. Because of its features and advantages, running ASP.NET in an out-of-process worker process is recommended for production sites.

  • Recycle processes periodically   You should recycle processes periodically, for both stability and performance. Over long periods of time, resources with memory leaks and bugs can affect Web server throughput, and recycling processes cleans up memory from these types of problems. However, you should balance the requirement to periodically recycle with recycling too often, because the cost of stopping the worker process, reloading pages, and re-obtaining resources and data can override the benefits of recycling.

    ASP.NET Web applications that run on Windows Server 2003 and IIS 6.0 do not require an adjustment to the process model, because ASP.NET will use the IIS 6.0 process model settings.

  • Set the number of threads per worker process correctly for your application   The request architecture of ASP.NET tries to achieve a balance between the number of threads that are executing requests and available resources. The architecture allows only the number of concurrently executing requests for which CPU power available. This technique is known as thread gating. However, there are conditions in which the thread-gating algorithm does not work well. You can monitor thread gating in the Windows Performance monitor using the Pipeline Instance Count performance counter that is associated with the ASP.NET Applications performance object.

    When an ASP.NET Web page calls an external resource, such as when it accesses a database or processes ASP.NET Web service requests, the page request generally stops until the external resource responds. This frees the CPU to process other threads. If another request is waiting to be processed and a thread is free in the thread pool, the waiting request starts to process. The result can be many concurrently executing requests and many waiting threads in the ASP.NET worker process or application pool. This can hinder the Web server's throughput and adversely affect performance.

    To reduce this effect on performance, you can manually set the limit on the number of threads in the process. To do so, change the MaxWorkerThreads and MaxIOThreads attributes in the processModel section of the Machine.config file.

    Note

    Worker threads are for processing ASP.NET requests. IO threads are used to service data from files, databases, or ASP.NET Web services.

    The values that you assign to the process model attributes represent the maximum number of each type of thread per CPU in the process. For a two-processor computer, the maximum number is two times the set value. For a four-processor computer, it is four times the set value. The default settings are appropriate for one-processor computers and two-processor computers. However, 100 or 200 threads in the process for computers that have more than two processors can reduce performance. If there are too many threads in a process, it can slow down. The server must perform extra context switches, which causes the operating system to spend CPU cycles to maintain threads instead of to process requests. You can determine what the appropriate number of threads is by performance-testing your application.

  • For applications that rely extensively on external resources, enable Web gardening on multiprocessor computers   The ASP.NET process model helps enable scalability on multiprocessor computers by distributing work to several processes, one per CPU, each with processor affinity set to a CPU. This technique is sometimes referred to as Web gardening. Web applications can benefit from Web gardening if they use external resources extensively. For example, applications might benefit if they use a database server or if they call COM objects that have external dependencies. However, test the performance of a Web application in a Web garden before you enable Web gardening for a production Web site.

Coding Practices

The following guidelines suggest ways to write efficient code.

  • Do not rely on exceptions in your code   Exceptions can cause performance to decrease significantly. Therefore, avoid using them as a way to control normal program flow. If possible, include logic in your code to detect and handle conditions that would cause an exception. Common scenarios to detect in code include checking for null, parsing strings into numeric values, and checking for specific values before math operations. The following examples show code that could cause an exception and show alternative code that tests for a condition. Both examples produce the same result.

    // This is not recommended.
    try {
       result = 100 / num;
    }
    catch (Exception e) {
      result = 0;
    }
    
    // This is preferred.
    if (num != 0)
       result = 100 / num;
    else
      result = 0;
    
    ' This is not recommended.
    Try
       result = 100 / num
    Catch (e As Exception)
      result = 0
    End Try
    
    ' This is preferred.
    If Not (num = 0)
       result = 100 / num
    Else
      result = 0
    End If
    

Code Examples

How to and Walkthrough Topics

How to: View the ASP.NET Performance Counters Available on Your Computer

How to: Precompile ASP.NET Web Sites

Walkthrough: Using ASP.NET Output Caching with SQL Server

Walkthrough: Creating an AJAX-enabled Web Site

Back to top

See Also

Concepts

Monitoring ASP.NET Application Performance

Performance Counters for ASP.NET

Design and Configuration for Performance

Performance Considerations for Applications Using Services

Adding AJAX and Client Capabilities Roadmap

Reference

Back to top

Other Resources

ASP.NET Caching

Building a Web 2.0 Portal with ASP.NET 3.5: Learn How to Build a State-of-the-Art Ajax Start Page Using ASP.NET, .NET 3.5, LINQ, Windows WF, and More