ASP.NET 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.

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 Microsoft Ajax and partial-page rendering to accomplish tasks in browser code without performing a full postback. For example, you can use Ajax features to validate user input in the browser before the input is submitted to the server. For more information, see Microsoft Ajax Overview and Partial-Page Rendering Overview.

  • 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 IsPostBackproperty 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 Web Forms 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.

    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.

    For more information, see the ViewStateMode property.

  • 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.

  • 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 ASP.NET Data Access Content Map.

  • 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 or exceptionally large item, 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 paging 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. If 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.

  • Preload the application. You can improve the initial startup and response time of an application by preloading it before users make any requests. You can preload an application in the following ways:

    • The IIS application pool warmup feature. This feature is activated by an HTTP request and is intended for use in most ASP.NET applications. To perform application warmup, IIS launches a worker process and then preloads the CLR and any required assemblies. Next, it uses an HTTP request simulator to mimic a real request, which triggers remaining start-up tasks such as compiling and caching pages, and creating database connections. To use this approach, write custom start-up code in the Application_Start method in Global.asax. Then configure IIS application warmup (in the applicationHost.config file) for the URL of the application. For information about how to configure IIS for application warmup, see Configuration Paths <ConfigPaths>.

      Note

      IIS application preload and warmup are only available in IIS 7.5 running on Windows Server 2008 or Windows 7.

    • The ASP.NET application preload manager. In .NET Framework 4, ASP.NET supports a custom application preload feature. This feature can be activated by either an HTTP or non-HTTP request, and it gives you programmatic control over all preload tasks. This approach is intended for relatively complex server application scenarios where the application needs a protocol-independent mechanism in order to carry out custom preload tasks. An example of such an application is Windows Communication Foundation (WCF). To use the ASP.NET application preload manager, you write a managed type that contains your preload code. The type must  implement the IProcessHostPreloadClient interface. You then configure your custom type as a preload provider type in IIS configuration in the applicationHost.config file.

    For information about how to configure IIS for custom preload types, see ASP.NET and IIS Configuration and Application Pools <applicationPools>.

  • Precompile Web site projects   By default, an ASP.NET Web site project 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, seeASP.NET Web Site Project Precompilation Overview. (This only applies to Web site projects; Web application projects are always precompiled. For information about the difference between Web site projects and Web applications, see Web Application Projects versus Web Site Projects in Visual Studio.)

  • 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. 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. If an application is intended to be available to everyone (that is, it does not require logon to view content), authentication is typically not required.

    • 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 Clause (Visual Basic) 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. (However, if other applications are running on the same server, and if they do need the modules you have removed from the machine.config file, you will have to add them to the application Web.config files of those applications.)

  • 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

ASP.NET Web Site Project Precompilation Overview

Walkthrough: Using ASP.NET Output Caching with SQL Server

Walkthrough: Creating an Ajax-Enabled Web Site

See Also

Concepts

Monitoring ASP.NET Application Performance

Performance Counters for ASP.NET

Design and Configuration for Performance

Performance Considerations for Applications Using Services

Other Resources

Chapter 4 — Architecture and Design Review of a .NET Application for Performance and Scalability

Chapter 6 — Improving ASP.NET Performance

Microsoft Patterns and Practices

ASP.NET Caching