ASP.NET 1.1 Performance Guidelines - Pages

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Srinath Vasireddy, Ashish Babbar, John Allen, and Alex Mackman


Trim Your Page Size

Processing large page sizes increases the load on the CPU, increases the consumption of network bandwidth, and increases the response times for clients. Avoid designing and developing large pages that accomplish multiple tasks, particularly where only a few tasks are normally executed for each request. Where possible logically partition your pages.

To trim your page size, you can do one or all of the following:

  • Use script includes for any static scripts in your page to enable the client to cache these scripts for subsequent requests. The following script element shows how to do this.
     <script language=jscript src="scripts\myscript.js">
  • Remove characters such as tabs and spaces that create white space before you send a response to the client. Removing white spaces can dramatically reduce the size of your pages. The following sample table contains white spaces.
     // with white space
hello world
     The following sample table does not contain white spaces.
     // without white space

Save these two tables in separate text files by using Notepad, and then view the size of each file. The second table saves several bytes simply by removing the white space. If you had a table with 1,000 rows, you could reduce the response time by just removing the white spaces. In intranet scenarios, removing white space may not represent a huge saving. However, in an Internet scenario that involves slow clients, removing white space can increase response times dramatically. You can also consider HTTP compression; however, HTTP compression affects CPU utilization.

You cannot always expect to design your pages in this way. Therefore, the most effective method for removing the white space is to use an Internet Server API (ISAPI) filter or an HttpModule object. An ISAPI filter is faster than an HttpModule; however, the ISAPI filter is more complex to develop and increases CPU utilization. You might also consider IIS compression. IIS compression can be added by using a metabase entry.

Additionally, you can trim page size in the following ways:

  • Disable view state when you do not need it. For more information, see "View State" later in this chapter.
  • Limit the use of graphics, and consider using compressed graphics.
  • Consider using cascading style sheets to avoid sending the same formatting directives to the client repeatedly.
  • Avoid long control names; especially ones that are repeated in a DataGrid or Repeater control. Control names are used to generate unique HTML ID names. A 10-character control name can easily turn into 30 to 40 characters when it is used inside nested controls that are repeated.

Note When using the ASP.NET process model, the ASP.NET worker process sends responses back to the client, it first sends them through IIS in 31-kilobyte (KB) chunks. This applies to .NET Framework 1.1, but it could change in future versions. The more 31-KB chunks that ASP.NET has to send through IIS, the slower your page runs. You can determine how many chunks ASP.NET requires for your page by browsing the page, viewing the source, and then saving the file to disk. To determine the number of chunks, divide the page size by 31.


Enable Buffering

Because buffering is enabled by default, ASP.NET batches work on the server and avoid chatty communication with the client. The disadvantage to this approach is that for a slow page, the client does not see any rendering of the page until it is complete. You can use Response.Flush to mitigate this situation because Response.Flush sends output up to that point to the client. Clients that connect over slow networks affect the response time of your server because your server has to wait for acknowledgements from the client to proceed. Because you sent headers with the first send, there is no chance to do it later.

If buffering is turned off, you can enable buffering by using the following methods:

  • Enable buffering programmatically in a page.
     // Response.Buffer is available for backwards compatibility; do not use.
     Response.BufferOutput = true;
  • Enable buffering at the page level by using the @Page directive.
     <%@ Page Buffer = "true" %>
  • Enable buffering at the application or computer level by using the <pages> element in the Web.config or Machine.config file.
     <pages buffer="true" …>

When you run your ASP.NET application by using the ASP.NET process model, it is even more important to have buffering enabled. The ASP.NET worker process first sends responses to IIS in the form of response buffers. After the ISAPI filter is running, IIS receives the response buffers. These response buffers are 31 KB in size., After IIS receives the response buffers, it then sends that actual response back to the client. With buffering disabled, instead of using the entire 31-KB buffer, ASP.NET can only send a few characters to the buffer. This causes extra CPU processing in both ASP.NET as well as in IIS. This may also cause memory consumption in the IIS process to increase dramatically.

Use Page.IsPostBack to Minimize Redundant Processing

Use the Page.IsPostBack property to ensure that you only perform page initialization logic when a page is first loaded and not in response to client postbacks. The following code fragment shows how to use the Page.IsPostBack property.

if (Page.IsPostBack == false) {
  // Initialization logic
} else {
  // Client post-back logic

Partition Page Content to Improve Caching Efficiency and Reduce Rendering

Partition the content in your page to increase caching potential. Partitioning your page content enables you to make different decisions about how you retrieve, display, and cache the content. You can use user controls to segregate static content, such as navigational items, menus, advertisements, copyrights, page headers, and page footers. You should also separate dynamic content and user-specific content for maximum flexibility when you want to cache content.

Ensure Pages Are Batch Compiled

As the number of assemblies that are loaded in a process grows, the virtual address space can become fragmented. When the virtual address space is fragmented, out-of-memory conditions are more likely to occur. To prevent a large number of assemblies from loading in a process, ASP.NET tries to compile all pages that are in the same directory into a single assembly. This occurs when the first request for a page in that directory occurs. Use the following techniques to reduce the number of assemblies that are not batch compiled:

  • Do not mix multiple languages in the same directory. When multiple languages such as C# or Visual Basic .NET are used in pages in the same directory, ASP.NET compiles a separate assembly for each language.
  • Ensure content updates do not cause additional assemblies to be loaded. For more information, see "Deployment Considerations" later in this chapter.
  • Ensure that the debug attribute is set to false at the page level and in the Web.config file, as described in the following section.

Ensure Debug Is Set to False

When debug is set to true, the following occurs:

  • Pages are not batch compiled.
  • Pages do not time out. When a problem occurs, such as a problem with a Web service call, the Web server may start to queue requests and stop responding.
  • Additional files are generated in the Temporary ASP.NET Files folder.
  • The System.Diagnostics.DebuggableAttribute attribute is added to generated code. This causes the CLR to track extra information about generated code, and it also disables certain optimizations.

Before you run performance tests and before you move your application into production, be sure that debug is set to false in the Web.config file and at the page level. By default, debug is set to false at the page level. If you do need to set this attribute during development time, it is recommended that you set it at the Web.config file level, as shown in the following fragment.

<compilation debug="false" ... />

The following shows how to set debug to false at the page level.

<%@ Page debug="false" ... %>

Note A common pitfall is to set this attribute at the page level during development and then forget to set it back when the application is moved to production.

Optimize Expensive Loops

Expensive loops in any application can cause performance problems. To reduce the overhead that is associated with code inside loops, you should follow these recommendations:

* Avoid repetitive field or property access. * Optimize code inside the loop. * Copy frequently called code into the loop. * Replace recursion with looping. * Use For instead of ForEach in performance-critical code paths.

Consider Using Server.Transfer Instead of Response.Redirect

Response.Redirect sends a metatag to the client that makes the client send a new request to the server by using the new URL. Server.Transfer avoids this indirection by making a server-side call. When you use Server.Transfer, the URL in the browser does not change, and load test tools may incorrectly report the page size because different pages are rendered for the same URL.

The Server.Transfer, Response.Redirect, and Response.End methods all raise ThreadAbortException exceptions because they internally call Response.End. The call to Response.End causes this exception. Consider using the overloaded method to pass false as the second parameter so that you can suppress the internal call to Response.End.


Use Client-Side Validation

Prevalidating data can help reduce the round trips that are required to process a user's request. In ASP.NET, you can use validation controls to implement client-side validation of user input.

Note Ensure that you also use server-side validation for security reasons.


For more information on validation controls, see the following:

Personal tools