الأحد، 26 أبريل 2009

ASP Tips to Improve Performance and Style 5

ASP Tips to Improve Performance and Style
 
Batch Inline Script and Response.Write Statements
The VBScript syntax <% = expression %> writes the value of "expression" to the ASP output stream. If response buffering is not turned on, then each of these statements results in writing data to the browser over the network in many small packets. This is slow. Also, interspersing small amounts of script and HTML causes switching between the script engine and HTML, reducing performance. Thus, use the following tip: Replace closely-bunched inline expressions with one call to Response.Write. For example, in the following sample, there is one write to the response stream per field per row, and many switches between VBScript and HTML per row:
*******************
<table> <% For Each fld in rs.Fields %>     <th><% = fld.Name %></th> <% Next While Not rs.EOF %>   <tr>   <% For Each fld in rs.Fields %>      <td><% = fld.Value %></td>    <% Next   </tr>    <% rs.MoveNext Wend %> </table>
*********************** 
The more efficient code, below, has one write to the response stream per row. All of the code is contained within one VBScript block:
*********************
<table> <%   For each fld in rs.Fields       Response.Write ("<th>" & fld.Name & "</th>" & vbCrLf)   Next   While Not rs.EOF     Response.Write ("<tr>")     For Each fld in rs.Fields %>       Response.Write("<td>" & fld.Value & "</td>" & vbCrLf)     Next     Response.Write "</tr>"   Wend %> </table>
*************************** 
This tip has a much bigger effect when response buffering is disabled. It's best to enable response buffering, and then see if batching Response.Write helps performance.
(In this particular example, the nested loop that builds the body of the table (While Not rs.EOF...) can be replaced by a carefully constructed call to GetString.)

Use Response.IsClientConnected Before Embarking on Long Trips

If the user gets impatient, he or she may abandon your ASP page before you even start executing their request. If he clicks Refresh or moves to a different page on your server, you will have a new request sitting at the end of the ASP request queue and a disconnected request sitting in the middle of the queue. Often this happens when your server is under high load (so it has a long request queue, with correspondingly high response times) and this only makes the situation worse. There's no point executing an ASP page (especially a slow, heavyweight ASP page) if the user is no longer connected. You can check for this condition by using the Response.IsClientConnected property. If it returns False, you should call Response.End and abandon the rest of the page. In fact, IIS 5.0 codifies this practice—whenever ASP is about to execute a new request, it checks to see how long the request has been in the queue. If it has been there for more than 3 seconds, ASP will check to see if the client is still connected and immediately terminate the request if it's not. You can use the AspQueueConnectionTestTime setting in the metabase to adjust this timeout of 3 seconds.
If you have a page that takes a very long time to execute, you may also want to check Response.IsClientConnected at intervals. When response buffering is enabled, it is a good idea to do Response.Flush at intervals to give the user the impression that something is happening.
Note   On IIS 4.0, Response.IsClientConnected will not work correctly unless you first do a Response.Write. If buffering is enabled, you'll also need to do a Response.Flush. On IIS 5.0, there is no need for this—Response.IsClientConnected works fine. In any case, Response.IsClientConnected has some costs, so only use it before an operation that takes at least, say 500 milliseconds (that's a long time if you're trying to sustain a throughput of dozens of pages per second). As a general rule of thumb, don't call it in every iteration of a tight loop, such as when painting the rows of a table—perhaps every 20th or 50th row of the table, instead.

Instantiate Objects Using the <OBJECT> Tag

If you need to refer to objects that might not be used in all code paths (especially Server- or Application-scoped objects), declare them by using the <object runat=server id=objname> tag in Global.asa rather than using the Server.CreateObject method. Server.CreateObject creates the object immediately. If you don't use that object later, you end up wasting resources. The <object id=objname> tag declares objname, but objname isn't actually created until the first time that one of its methods or properties are used.
This is another example of lazy evaluation.

Use TypeLib Declarations for ADO and Other Components

When using ADO, developers often include adovbs.txt to get access to ADO's various constants. This file must be included on every page that wants to use the constants. This constant file is fairly large, adding a lot of overhead to every ASP page's compilation time and script size.
IIS 5.0 introduces the ability to bind to a component's type library. This allows you to reference the type library once and use it on every ASP page. Each page does not pay the penalty of compiling the constant file, and component developers do not have to build VBScript #include files for use in ASP.
To access the ADO TypeLib, place one of the following statements in Global.asa.
************************
<!-- METADATA NAME="Microsoft ActiveX Data Objects 2.5 Library"               TYPE="TypeLib" UUID="{00000205-0000-0010-8000-00AA006D2EA4}" -->
*************************** 
or
******************
<!-- METADATA TYPE="TypeLib"               FILE="C:\Program Files\Common Files\system\ado\msado15.dll" -->
******************************* 

Take Advantage of Your Browser's Validation Abilities

Modern browsers have advanced support for features such as XML, DHTML, Java applets, and the Remote Data Service. Take advantage of these features whenever you can. All of these technologies can save round trips to the Web server by performing client-side validation as well as data caching. If you are running a smart browser, the browser is capable of doing some validation for you (for example, checking that a credit card has a valid checksum before executing POST). Again, take advantage of this whenever you can. By cutting down on client-server round trips, you'll reduce the stress on the Web server and cut down network traffic (though the initial page sent to the browser is likely to be larger), as well as any back-end resources that the server accesses. Furthermore, the user will not have to fetch new pages as often, improving the experience. This does not relieve you of the need to do server-side validation—you should always do server-side validation as well. This protects against bad data coming from the client for some reason, such as hacking, or browsers that don't run your client-side validation routines.
Much has been made of creating "browser-independent" HTML. This concern often discourages the developer from taking advantage of popular browser features that could benefit performance. For truly high-performance sites that must be concerned about browser "reach," a good strategy is to optimize pages for the popular browsers. Browser features can be easily detected in ASP using the Browser Capabilities Component. Tools such as Microsoft FrontPage can help you design code that works with the browsers and HTML versions you wish to target.

Avoid String Concatenation in Loops

Many people build a string in a loop like this:
**********************
s = "<table>" & vbCrLf For Each fld in rs.Fields     s = s & " <th>" & fld.Name & "</th> " Next  While Not rs.EOF     s = s & vbCrLf & " <tr>"     For Each fld in rs.Fields         s = s & " <td>" & fld.Value & "</td> "     Next     s = s & " </tr>"     rs.MoveNext Wend  s = s & vbCrLf & "</table>" & vbCrLf Response.Write s
************************** 
There are several problems with this approach. The first is that repeatedly concatenating a string takes quadratic time; less formally, the time that it takes to run this loop is proportional to the square of the number of records times the number of fields. A simpler example should make this clearer.
********************
s = "" For i = Asc("A") to Asc("Z")     s = s & Chr(i) Next
*********************** 
On the first iteration, you get a one-character string, "A". On the second iteration, VBScript has to reallocate the string and copy two characters ("AB") into s. On the third iteration, it has to reallocate s again and copy three characters into s. On the Nth (26th) iteration, it has to reallocate and copy N characters into s. That's a total of 1+2+3+...+N which is N*(N+1)/2 copies.
In the recordset example above, if there were 100 records and 5 fields, the inner loop would be executed 100*5 = 500 times and the time taken to do all the copying and reallocation would be proportional to 500*500 = 250,000. That's a lot of copying for a modest-sized recordset.
In this example, the code could be improved by replacing the string concatenation with Response.Write() or inline script (<% = fld.Value %>). If response buffering is turned on (as it should be), this will be fast, as Response.Write just appends the data to the end of the response buffer. No reallocation is involved and it's very efficient.
In the particular case of transforming an ADO recordset into an HTML table, consider using GetRows or GetString.
If you concatenate strings in JScript, it is highly recommended that you use the += operator; that is, use s += "some string", not s = s + "some string".


What can you do with the new Windows Live? Find out

ليست هناك تعليقات: