Section 17.6. Performance


17.6. Performance

Performance is often an important issue in computer applications, especially in web applications receiving a large number of requests . One obvious way to improve performance is to buy faster hardware with more memory. But you can also tune your code to enhance performance in many ways, some of them significant. We'll begin by examining some of the areas specific to ASP.NET that offer the greatest performance improvements and then examine some of the general .NET topics related to improving performance.

Several Microsofties involved with writing the .NET Framework used the word performant to mean that something is delivering higher performance. We can't find it in any dictionary, but it seems like a good word.


17.6.1. ASP.NET-Specific Issues

Correctly using the following features of ASP.NET offers the greatest performance improvements when an ASP.NET application is running.

17.6.1.1. Session state

Session state is a wonderful thing, but not all applications or pages require it. For any that do not, disable it. You can disable session state for a page by setting the EnableSessionState attribute in the Page directive to false , as in this example:

 <%@ Page Language="C#" EnableSessionState="false"%> 

If a page will not be creating or modifying session variables but still needs to access them, set the session state to read-only:

 <%@ Page Language="C#" EnableSessionState="ReadOnly"%> 

By default, web services do not have session state enabled. They only have access to session state if the EnableSession property of the WebMethod attribute is set to true :

 [WebMethod(EnableSession=true)] 

Session state can be disabled for an entire application by editing the sessionState section of the application's web.config file:

 <sessionState  mode="off" /> 

Session state can be stored in one of three ways:

  • In-process

  • Out-of-process, as a Windows service

  • Out-of-process, in a SQL Server database

Each has advantages and disadvantages. Storing session state in-process is by far the most performant. The out-of-process stores are necessary in web farm or web garden scenarios (see the section "Web gardening and web farming" later in this chapter) or if the data must not be lost if a server or process is stopped and restarted.

For a complete discussion of session state, see Chapter 6.

17.6.1.2. View state

Automatic view state management is another great feature of ASP.NET server controls that enables the controls to show property values correctly after a round trip with no work on the part of the developer. However, there is a performance penalty. This information is passed back and forth via a hidden field, which consumes bandwidth and takes time to process. To see the amount of data used in view state, enable tracing and look at the ViewState column of the Control Tree table displayed as part of the trace ouput.

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

 <asp:TextBox         id="txtBookName"         text="Enter book name."         toolTip="Enter book name here."         EnableViewState="false"         runat="server" /> 

You can disable view state for an entire page by setting the EnableViewState attribute of the Page directive to false , as in this example:

 <%@ Page Language="C#"  EnableViewState="false" %> 

17.6.1.3. Caching

Use output and data caching whenever possible. This is especially valuable for database queries that return relatively static data or have a limited range of query parameters. Effective use of caching can have a profound effect on the performance of a web site.

17.6.1.4. Server controls

Server controls are convenient and offer many advantages. In VS2005, they are practically the default type of control. However, they have a certain amount of overhead and are sometimes not the optimal type of control to use.

In general, if you do not need to manipulate a control programmatically, do not use a server control. Use a classic HTML control instead. For example, if placing a simple label on a page, there will be no need to use a server control unless you need to read or change the value of the label's Text property.

If you need to substitute values into HTML sent to the client browser, you can achieve the desired result (without using a server control) by using data binding or a simple rendering. For example, the following example shows three ways of displaying a hyperlink in a browser:

 <script language="C#" runat="server">         string strLink = "www.anysite.com";         void Page_Load(Object sender, EventArgs e)         {             //..retrieve data for strLink here             //  Call the DataBind method for the page.             DataBind(  );         }     </script>     <%--the server control is not necessary...--%>     <a href='<%# strLink %>' runat="server">The Name of the Link</a>     <br><br>     <%-- use DataBinding to substitute literals instead...--%>     <a href='<%# strLink %>' > The Name of the Link</a>     <br><br>     <%-- or a simple rendering expression...--%>     <a href='<%= strLink %>' > The Name of the Link</a> 

17.6.1.5. Web gardening and web farming

Adding multiple processors to a computer is called web gardening . The .NET Framework takes advantage of this by distributing work to several processes, one process per CPU.

For truly high-traffic sites, multiple web server machines can work together to serve the same application. This is referred to as a web farm .

At the least, locating the web server on one machine and the database server on another will buy a large degree of stability and scalability.

17.6.1.6. Round trips

Round trips to the server are expensive. In low bandwidth situations, they are slow for the client, and in high-volume applications, they bog down the server and inhibit scaling. You should design your applications to minimize round trips.

The only truly essential round trips to the server are those that read or write data. Most validation and data manipulations can occur on the client browser. ASP.NET server controls do this automatically for validation with uplevel browsers (IE 4, 5, and 6, or any browser that supports ECMAScript).

When developing custom server controls, having the controls render client-side code for uplevel browsers will reduce the number of round trips.

Another way to minimize round trips is to use the IsPostBack property in the Page_Load method. Often, you will want the page to perform some process the first time the page loads, but not on subsequent postbacks. For example, the following code shows how to make code execution conditional on the IsPostBack property:

  void Page_Load(Object sender, EventArgs e) {    if (! IsPostBack)  {       //  Do the expensive operations only the       //  first time the page is loaded.    } } 

For a complete discussion of the IsPostBack property, see Chapter 3.

17.6.2. General .NET Issues

Many of the performance enhancements that affect an ASP.NET application are general ones that apply to any .NET application. This section lists some of the major .NET-related areas to consider when developing your ASP.NET applications.

17.6.2.1. String concatenation

Strings are immutable in the .NET Framework. This means that methods and operators that appear to change the string are actually returning a modified copy of the string. This has huge performance implications. If you're doing a lot of string manipulation, using the StringBuilder class is much faster.

Consider the code shown in Example 17-27. It measures the time to create a string from 10,000 substrings in two different ways. The first time, a simple string concatenation is used, and the second time the StringBuilder class is used. If you want to see the resulting string, uncomment the two commented lines in the code.

Example 17-27. String concatenation benchmark in C#, StringConcat-cs.aspx
 <%@ Page Language="C#" %> <script runat="server">    void Page_Load(Object Source, EventArgs E)    {       int intLimit = 10000;       DateTime startTime;       DateTime endTime;       TimeSpan elapsedTime;       string strSub;       string strWhole = "";       //  Do string concat first       startTime = DateTime.Now;       for (int i=0; i < intLimit; i++)       {          strSub = i.ToString(  );          strWhole = strWhole + " " + strSub;       }       endTime = DateTime.Now;       elapsedTime = endTime - startTime;       lblConcat.Text = elapsedTime.ToString(  ); //      lblConcatString.Text = strWhole;       //  Do stringBuilder next       startTime = DateTime.Now;       StringBuilder sb = new StringBuilder(  );       for (int i=0; i < intLimit; i++)       {          strSub = i.ToString(  );          sb.Append(" ");          sb.Append(strSub);       }       endTime = DateTime.Now;       elapsedTime = endTime - startTime;       lblBuild.Text = elapsedTime.ToString(  ); //      lblBuildString.Text = sb.ToString(  );    } </script> <html>    <body>    <form runat="server">       <h1>String Concatenation Benchmark</h1>       Concatenation:&nbsp;&nbsp;       <asp:Label          id="lblConcat"          runat="server"/>       <br/>       <asp:Label          id="lblConcatString"          runat="server"/>       <br/>       <br/>       StringBuilder:&nbsp;&nbsp;       <asp:Label          id="lblBuild"          runat="server"/>       <br/>       <asp:Label          id="lblBuildString"          runat="server"/>     </form>    </body> </html> 

When this page is run, you should see something like Figure 17-8. The difference between the two techniques is dramatic: the StringBuilder 's Append method is more than 300 times faster than string concatenation.

Figure 17-8. String concatenation

17.6.2.2. Minimize exceptions

You can use try...catch blocks to control program flow. However, this coding technique is a serious impediment to performance. You will do much better if you first test whether some condition will cause a failure; if so, code around it.

For example, rather than dividing two integers inside a TRy...catch block and catching any Divide By Zero exceptions thrown, first test if the divisor is zero; if it is, do not do the operation. Similarly, it is as expensive to throw exceptions of your own creation though there are times when it cannot be avoided.

17.6.2.3. Use early binding

.NET languages allow both early and late binding. Early binding occurs when all objects are declared and the object type known at compile time. Late binding occurs when the object type is not determined until runtime, at which point the CLR determines the type of object it is working with.

Early binding is much faster than late binding , though the latter can be very convenient. Late binding is implemented with reflection, the details of which are beyond the scope of this book.

17.6.2.4. Use managed code

Managed code is more performant than unmanaged code. It may be worthwhile to port heavily used COM components to managed code.

17.6.2.5. Disable debug mode

When you deploy your application, remember to disable Debug mode. For a complete discussion of deployment issues, refer to Chapter 19.

17.6.3. Database Issues

Almost all applications involve some form of database access, and accessing data from a database is necessarily an expensive operation. Data access can be made more efficient, however, by focusing on several areas.

17.6.3.1. Stored procedures

When interacting with a database, using stored procedures is always much faster than the same operation passed in as a command string. This is because stored procedures are compiled and optimized by the database engine. Use stored procedures whenever possible.

17.6.3.2. Use DataReader class

There are two main ways to get data from a database: from a DataReader object or a DataSet object. The DataReader classes ( SqlDataReader , OleDbDataReader , or OracleDataReader ) are a much faster way of accessing data if all you need is a forward-only data stream.

17.6.3.3. Use SQL or Oracle classes rather than OleDB classes

Some database engines have managed classes specifically designed for interacting with that database. It is much better to use the database-specific classes rather than the generic OleDB classes. So, for example, it is faster to use a SqlDataReader rather than an OleDbDataReader .



Programming ASP. NET
Programming ASP.NET 3.5
ISBN: 0596529562
EAN: 2147483647
Year: 2003
Pages: 173

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net