Improved string handling performance for ASP _ Application techniques

Source: Internet
Author: User
Tags error handling memory usage repetition

Most Active Server Pages (ASP) applications use string concatenation to create data that is rendered to the user in HTML format. This article compares several methods for creating this HTML data stream, and in certain cases some methods are superior to other methods in performance. This article assumes that you already have some knowledge of ASP and visual Basic programming.

Directory

    • Brief introduction
    • ASP Design
    • string concatenation
    • Quick Solution
    • StringBuilder
    • Built-in methods
    • Test
    • Results
    • Summary

Brief introduction

When writing an ASP page, the developer actually creates a formatted text stream that is written to the Web client through the Response object provided by the ASP. There are a number of ways to create this text stream, and the method you choose will have a significant impact on the performance and scalability of your WEB application. Many times, when I helped clients optimize the performance of their WEB applications, it was found that one of the more effective ways to change the way HTML streams were created. This article will introduce several common techniques and test their impact on the performance of a simple ASP page.

ASP Design

Many ASP developers follow good software engineering principles and modularize their code as much as possible. This design typically uses a number of include files that contain functions that are formatted for a particular discontinuous part of the page. The string output of these functions, usually the HTML form code, creates a complete page from a variety of combinations. Some developers have improved this approach by moving these HTML functions into Visual Basic COM components, hoping to take full advantage of the extra performance that has been provided by compiled code.

Although this design approach is good, the method used to create strings that make up these discrete HTML code components will have a significant impact on the performance and scalability of the Web site, regardless of whether the actual operation is performed in an ASP include file or in a Visual Basic COM component.

string concatenation

Take a look at the code snippet for the following writehtml function. The parameter named data is just an array of strings that contain some data to be formatted as a table structure (for example, data returned from a database).

Function writehtml (Data)
Dim nrep for
nrep = 0 to
 SHTML = SHTML & vbCrLf _ 
   & "<tr><t D> "& (Nrep + 1) &" </TD><TD> "_ 
   & Data (0, Nrep) &" </TD><TD> "_ 
   ; Data (1, Nrep) & "</TD><TD>" _ 
   & Data (2, Nrep) & "</TD><TD>" _ 
   & Data ( 3, Nrep) & "</TD><TD>" _ 
   & Data (4, Nrep) & "</TD><TD>" _ 
   & Data (5, NR EP) & "</TD></TR>"
Next
writehtml = SHTML End
Function

This is a common way for many ASP and visual Basic developers to create HTML code. The text contained in the SHTML variable is returned to the calling code, which is then written to the client using Response.Write . Of course, this can also be expressed as a similar code for embedding pages that do not contain writehtml functions directly. The problem with this code is that the string data type (BSTR or basic string) used by ASP and visual Basic cannot actually change the length. This means that each time the string length changes, the original representation of the string in memory is corrupted, and a new representation is created that contains the new string data: This increases the amount of memory allocated and the allocation of memory. Of course, ASP and visual Basic have solved this problem for you, so the actual overhead is not immediately apparent. Allocating and releasing memory requires basic Run-time code to unlock individual locks, and therefore requires significant overhead. This problem becomes particularly noticeable when strings become large and large chunks of memory are allocated and unassigned quickly and continuously, as they would appear during a large string connection. Although this problem has little impact on single-user environments, it can cause serious performance and scalability problems in a server environment, such as an ASP application running on a WEB server.

Let's go back to the code snippet above: How many string assignment operations do you want to perform in this code? The answer is 16. In this case, & each application of the "" Operator will cause the string that the variable sHTML refers to be corrupted and recreated. As mentioned earlier, string allocation is expensive and increases as the string increases, so we can improve on this code.

Quick Solution

There are two ways to mitigate the effect of string concatenation, the first of which is to try to reduce the size of the string being processed, and the second is to try to reduce the number of string assignment operations performed. See the revised version of the writehtml code shown below.

Function writehtml (Data)
Dim nrep for
nrep = 0 to
 SHTML = SHTML & (vbCrLf _ 
   & "<tr>< ; Td> "& (Nrep + 1) &" </TD><TD> "_ 
   & Data (0, Nrep) &" </TD><TD> "_  
   &am P Data (1, Nrep) & "</TD><TD>" _ 
   & Data (2, Nrep) & "</TD><TD>" _ 
   & Data ( 3, Nrep) & "</TD><TD>" _ 
   & Data (4, Nrep) & "</TD><TD>" _ 
   & Data (5, NRe p) & "</TD></TR>")
Next
writehtml = SHTML End
Function

At first glance, it may be difficult to see the difference between this code and the previous code example. In fact, this code just sHTML = sHTML & adds parentheses outside the contents of the post. This actually reduces the size of the strings processed in most string concatenation operations by changing the precedence order. In the original code example, the ASP compiler looks at the expression to the right of the equal sign and evaluates it from left to right. As a result, there are 16 connection operations for each repetition, and these actions are for the ever-increasing sHTML progress. In the new version, we prompt the compiler to change the order of operations. It now evaluates the expression in order from left to right, from parentheses to outside parentheses. This technique allows each repetition to include 15 connection operations, which are for smaller strings that do not grow, and only one for the ever-increasing size sHTML . Figure 1 shows the comparison between this optimization method and the standard connection method in memory usage patterns.

Figure 1: Comparison of standard and parenthesis connections in memory usage patterns

In certain cases, the use of parentheses can have a significant impact on performance and scalability, which will be further explained later in this article.

StringBuilder

We've found a quick way to solve string concatenation problems, and in most cases this approach achieves the best balance between performance and investment. However, if you want to further improve the performance of building large strings, the second approach is to reduce the number of string allocation operations. To do this, you need to use StringBuilder. StringBuilder is a class that maintains configurable string buffers, manages new pieces of text that are inserted into this buffer, and assigns strings only when the length of the text exceeds the length of the string buffer. The Microsoft. NET framework provides such a class (System.Text.StringBuilder) free of charge and recommends that it be used in all string concatenation operations that are performed in that environment. In ASP and traditional Visual Basic environments, we cannot access this class, so we need to create it ourselves. The following is an example of the StringBuilder class created using Visual Basic 6.0 (for simplicity, error handling code is omitted).

Option Explicit ' default buffer initial size and growth factor Private Const def_initialsize As Long = 1000 Private Const def_growth As Long = 1000 ' slow  Flushing area size and growth private m_ninitialsize as long private m_ngrowth as long buffer and buffer counter private m_stext as String private m_nsize as Long private m_npos as Long private Sub class_initialize () ' Sets the default value for size and growth m_ninitialsize = def_initialsize M_ngrowth = Def_growth ' initialization buffer Initbuffer end Sub ' Sets the initial size and growth number public Sub Init (ByVal initialsize as Long, ByVal growth as Long) I F initialsize > 0 Then m_ninitialsize = initialsize If growth > 0 Then m_ngrowth = growth End Sub ' Initialize buffer Private Sub initbuffer () m_nsize =-1 M_npos = 1 End Sub ' increases buffer Private Sub Grow (Optional minimimgrowth as Long) ' initialization buffer (if necessary 
  ) If m_nsize =-1 Then m_nsize = m_ninitialsize M_stext = space$ (m_ninitialsize) Else ' just grow Dim ngrowth as Long Ngrowth = IIf (M_ngrowth > Minimimgrowth, M_ngrowth, minimimgrowth) m_nsize = m_nsize + ngrowth M_stext = m_s Text & space$ (ngrowth) End-If-sub ' adjusts the buffer size to the size of the current use Private Sub Shrink () If m_nsize > M_npos Then m_nsize = m_npos-1 M_stext = rtrim$ (m_stext) End If End Sub ' Add a single text string Private Sub appendinternal (ByVal Text as String) If (M_npos + Len (Text)) ; M_nsize Then Grow Len (text) mid$ (M_stext, M_npos, Len (text)) = text M_npos = M_npos + len (text) End Sub ' Add some text strings publ IC Sub Append (ParamArray text ()) Dim Narg as Long for narg = 0 to UBound (text) appendinternal CStr (text (narg)) Next n Arg End Sub ' Returns the current string data and adjusts the buffer size public Function ToString () as String If m_npos > 0 Then Shrink ToString = M_stex
 T Else ToString = "End If end Function" Clears buffer and reinitialize public Sub clear () Initbuffer End Sub

The basic principle used in this class is to use a variable () as a string buffer at the class level m_sText , and to use the space$ function to populate the buffer with a space character to set it to a specific size. If you want to connect more text to existing text, use the mid$ function to insert text in the correct position after checking the buffer size enough to hold the new text. The ToString function returns the text currently stored in the buffer and resizes the buffer to fit the correct length of the text. The ASP code that uses StringBuilder looks like this:

Function writehtml (Data)
Dim OSB
Dim Nrep
Set OSB = Server.CreateObject ("Stringbuildervb.stringbuilder")
' Initialize buffer with size and growth factor
osb.init 15000, 7500 for
nrep = 0 to
 ' osb.append ' <TR><TD> ', (Nrep + 1), "</TD><TD>", _ 
   data (0, Nrep), "</TD><TD>", _ 
   data (1, Nrep), "</TD><TD> ", _ 
   data (2, Nrep)," </TD><TD> ", _ 
   data (3, Nrep)," </TD><TD> ", _ 
   data (4, Nrep ), "</TD><TD>", _ 
   Data (5, Nrep), "</TD></TR>"
Next
writehtml = osb.tostring ()
Set OSB =
Nothing End Function

Using StringBuilder requires a certain amount of overhead because it must be created every time this class is used, and the DLL containing this class must be loaded when the first class instance is created. Overhead is also required for additional method calls to the StringBuilder instance. When using the Parenthesized & method, howStringBuilder executes depends on several factors, including the number of connections, the size of the string to build, and the performance of the initialization parameters of the selected StringBuilder string buffer. Note that in most cases, the amount of space required in the buffer is estimated to be slightly higher than it is to keep growing.

Built-in methods

ASP contains a very quick way to create HTML code, just call Response.Writemultiple times. The Write function uses an implicitly optimized string buffer that provides very good performance characteristics. The modified writehtml code looks like this:

Function writehtml (Data)
Dim nrep for
nrep = 0 to
 Response.Write "<TR><TD>" 
 Response.Write (Nrep + 1) 
 Response.Write "</TD><TD>"
 Response.Write Data (0, Nrep) 
 Response.Write "</TD><TD>"
 Response.Write Data (1, nrep) 
 Response.Write "</TD><TD>" 
 Response.Write Data (2, Nrep) 
 Response.Write "</TD><TD>"
 Response.Write Data (3, Nrep) 
 Response.Write "</td><td > "
 Response.Write Data (4, Nrep) 
 Response.Write" </TD><TD> "
 Response.Write data (5, NREP) 
 Response.Write "</TD></TR>"
Next end
Function

While this code is likely to provide us with the best performance and scalability, the encapsulation has been compromised to some extent because the code inside the function is now written directly to the Response stream, so the calling code loses a certain amount of control. In addition, moving this code (for example, moving to a COM component) becomes more difficult because this function has a dependency on the Response stream.

Test

The four methods mentioned above are tested by a simple ASP page that contains a single table that provides data from a virtual string array. We use the application Center test® (ACT) to target a single server in a 100mb/sec network from a single client (Windows®xp professional,piii-850mhz,512mb RAM) (Windows Advanced Server, dual PIII-1000MHZ,256MB RAM) performed the test. ACT is configured to use 5 threads to simulate the load of 5 users when they connect to a Web site. Each test includes a 20-second warm-up time and a subsequent 100-second load time, creating as many requests as possible during the load.

By changing the number of repetitions in the main table loop, run the test repeatedly for a different number of connection operations, as shown in the code snippet in the writehtml function. Each test that runs is performed using the four different methods mentioned above.

Results

The following series of charts shows the impact of various methods on the overall application throughput and the response time for ASP pages. These charts allow us to understand how many requests the application supports and how long it takes the user to wait for the page to download to the browser.

Table 1: Description of the connection method abbreviations used

method Abbreviation Description
RESP Built-in Response.Write method
CAT Standard connection (" & ") method
PCAT Parenthesized Connection (" & ") method
Bldr StringBuilder method

This test is a far cry from the actual situation in simulating the workload of a typical ASP application, and it is obvious from table 2 that this page is not particularly large even if repeated 420 times. Now many complex ASP pages are relatively high in these numbers, and settings may be beyond the limits of this test scope.

Table 2: Test Sample page size and number of connections

Number of repetitions Number of connections Page size (in bytes)
15 240 2,667
30 480 4,917
45 720 7,167
60 960 9,417
75 1,200 11,667
120 1,920 18,539
180 2,880 27,899
240 3,840 37,259
300 4,800 46,619
360 5,760 55,979
420 6,720 62,219

Figure 2: Throughput Results graph

As you can see from the chart in Figure 2, the multiple Response.Write Method (RESP) provides us with the best throughput in the test's entire repeat test range, as we have expected. Surprisingly, the drop in standard string concatenation (CAT) was so great, and the Parenthesized method (PCAT) was still a lot better performing 300 times. At approximately 220 times, the performance improvement of the string cache is greater than the intrinsic overhead of the StringBuilder method (Bldr), and above that, the extra overhead required to use StringBuilder in this ASP page is worthwhile.

Figure 3: Response Time result graph

Figure 4: The response time result graph for omitting CAT

The chart in Figure 3 and Figure 4 shows the response time (in milliseconds) measured by "to the first byte of Time". Because the response time for standard string concatenation methods (CAT) increases too quickly, a chart that does not include this method is provided (Figure 4) to analyze the differences between other methods. It is noteworthy that the multiple Response.Write Method (RESP) and the StringBuilder Method (BLDR) present an approximate linear increase with the increase in the number of repetitions, while the standard connection method (CAT) and Parenthesized methods (PCAT) begin to increase rapidly after exceeding a certain threshold value.

Summary

This article focuses on how to apply different string-building techniques in an ASP environment, which also applies to all scenarios where you create a large string using Visual Basic code, such as creating an XML document manually. The following guidelines can help you determine which method is best for your needs.

    • First try the parenthetical " & " method, especially if you are working with existing code. This approach has minimal impact on the structure of your code, but you'll find that your application's performance will be significantly enhanced, even beyond your intended target.
    • Use Response.Writewithout destroying the required encapsulation level. Using this method, you can avoid unnecessary in-memory string processing to provide optimal performance.
    • Use StringBuilder to build a truly large or connected string.

Although you may not see this performance growth as shown in this article, I have used these techniques in real-world ASP WEB applications that require very little extra effort to improve performance and scalability.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.