Improve the best choice for ASP performance

xiaoxiao2021-04-01  217

The best choice of ASP improve performance: Iasky | Article Source: Unknown

ASP developers are constantly working hard to achieve better performance and scalability in their design projects. Fortunately, there are many books and sites that provide good advice in this regard. However, these recommendations are the conclusions obtained from the structure of the ASP platform, and there is no measurement for the improvement of the actual performance. Since these recommendations require more complex coding processes and reduce encoding readability, developers can only measure whether their ASP applications can be paid in order to improve their ASP applications without causing actual operation.

This article is divided into two parts, I will introduce some performance test results to help developers to determine if a particular initiative is worthy of the future project, but can be updated for the original project. In the first part I will review some basic issues developed by ASP. In the second part, some Optimization ADO functions will be involved, and their results are compared to the ASP page that calls VB COM objects. These results are very eye-catching, even sometimes surprising.

In this article, we will answer the following questions:

* What is the most effective way to write ASP's content written in response stream?

* Is the buffer should be turned on?

* Do you should consider adding comments to the ASP code?

* Is the default language should be explicitly set for the page?

* If you don't need it, should you close the Sems status?

* Whether the script logic should be placed in a subroutine and a function area?

* What is the impact of using the included file?

* What load is applied when performing error processing?

* Set whether a context process has an impact on performance?

All tests are done with Microsoft's Web Application Key Tools (WAST), this is a free tool, which can be found here. I created a simple Test script with WAST, repeatedly calls the ASP page test described below (more than 70,000 times). The reaction time is based on the average last byte total time (TTLB), that is, the time to receive the last bit data from the server from the server. Our test server is a Pentium 166, which is 196MB, and the client is Pentium 450, and memory is 256MB. You may think that the performance of these machines is not very advanced, but don't forget, we are not to test the capacity of the server, we just want to test the time used by the server each time you process. These machines do not do other jobs during the test. WAST test scripts, test reports, and all ASP test pages are included in the zip file, you can review and test themselves. What is the most effective way to write the content of the ASP in response? One of the most important reasons used to use ASP is to generate dynamic content on the server. Therefore, it is clear that the starting point of our test is to determine the most suitable way to send dynamic content to the response stream. In a variety of options, there are two most basic: First, use the inline ASP tag, the other is to use the response.write statement.

To test these options, we created a simple ASP page that defines some variables and then inserts their values ​​into the table. Although this page is simple or practical, it allows us to separate and test some separate questions.

Use ASP inline mark

The first test includes using an inline ASP tag <% = x%>, where x is an assigned variable. So far, this method is the easiest to perform, and it keeps the page's HTML section a format that is easy to read and maintain.

<% OPTION Explicit

DIM FIRSTNAME

DIM Lastname

Dim MiddleInitial

DIM Address

DIM City

DIM State

Dim Phonenumberdim FaxNumber

DIM EMAIL

Dim Birthdate

Firstname = "john"

MiddleInitial = "q"

Lastname = "public"

Address = "100 main street"

City = "new york"

State = "NY"

Phonenumber = "1-212-555-1234"

FAXNUMBER = "1-212-555-1234"

Email = "john@public.com"

Birthdate = "1/1/1950"

%>

Response test </ title></p> <p></ HEAD></p> <p><Body></p> <p><H1> Response Test </ h1></p> <p><Table></p> <p><TR> <TD> <B> First Name: </ b> </ td> <td> <% = firstname%> </ td> </ tr></p> <p><TR> <TD> <B> Middle Initial: </ b> </ td> <td> <% = middleinitial%> </ td> </ tr></p> <p><Tr> <TD> <B> Last Name: </ b> </ td> <td> <% = lastname%> </ td> </ tr></p> <p><TR> <TD> <B> Address: </ b> </ td> <td> <% = address%> </ td> </ tr></p> <p><TR> <TD> <b> city: </ b> </ td> <td> <% = city%> </ td> </ tr></p> <p><TR> <TD> <B> State: </ b> </ td> <td> <% = state%> </ td> </ tr></p> <p><TR> <TD> <B> Phone Number: </ b> </ td> <td> <% = phonenumber%> </ td> </ tr></p> <p><TR> <TD> <B> Fax Number: </ b> </ td> <td> <% = faxNumber%> </ td> </ tr></p> <p><Tr> <TD> <B> Email: </ b> </ td> <td> <% = email%> </ td> <b> <tr> <td> <b> Birth Date: </ B> </ td> <td> <% = birthdate%> </ td> </ tr></p> <p></ Table></p> <p></ Body></p> <p></ Html></p> <p>/App1/response1.asp's full code</p> <p>Previously optimal (reaction speed) = 8.28 msec / Page</p> <p>Use the response.write statement in each line of HTML</p> <p>Many better learning documents suggest to avoid using the previous method. Its main reason is that during the output page and the processing page to apply a reaction time, if the web server has to transform between sending pure HTML and processing scripts, there is a problem that is called context transformation. Most of the programmers heard here, their first reaction is to package the original HTML every line in the response.write function.</p> <p>...</p> <p>Response.write ("<html>")</p> <p>Response.write ("<HEAD>")</p> <p>Response.write ("<title>")</p> <p>Response.write ("</ head>")</p> <p>Response.write ("<body>")</p> <p>Response.write ("<H1> Response Test </ h1>")</p> <p>Response.write ("<Table>")</p> <p>Response.write ("<tr> <td> <b> first name: </ b> </ td> <td>" & numbertname & "</ td> </ tr>")</p> <p>Response.write ("<tr> <td> <b> Middle Initial: </ b> </ td> <td>" & middleinitial & "</ td> </ tr>")</p> <p>...</p> <p>/App1/Response2.asp fragment</p> <p>Previously optimal (reaction speed) = 8.28 msec / Page</p> <p>Response time = 8.08 msec / page</p> <p>Difference = -0.20 msec (reduced 2.4%)</p> <p>We can see that using this method is very small in performance as compared with the method of using the inline mark, this may be because the page is loaded with a large pile of functions to the server. The biggest disadvantage of this method is that since the HTML is now embedded in the script, the script code becomes more lengthy, more difficult to read and maintain.</p> <p>Use packaging functions</p> <p>When we try to use the response.write statement, the most discouraged discovery may be that the response.write function cannot be placed at the end of each row at the end of each line. Therefore, when you read the source code from your browser, it is very good HTML, and now there is no end. I think your next discovery may make you a horrible: there is no sister function writern in the response object. So, a significant reaction is to create a packaging function for the Response.Write function to add a CRLF to each line. ...</p> <p>WriteCr ("<tr> <TD> <B> first name: </ b> </ td> <TD>" & firstname & "</ td> </ tr>")</p> <p>...</p> <p>Sub WriteCr (STR)</p> <p>Response.write (STR & VBCRLF)</p> <p>End Sub</p> <p>/App1/response4.asp fragment</p> <p>Previous best (reaction speed) = 8.08 msec / page</p> <p>Reaction time = 10.11 msec / page</p> <p>Difference = 2.03 msec (add 25.1%)</p> <p>Of course, since this method effectively doubles the number of function calls, its impact on performance is also obvious, so we must avoid all costs. Ironically, CRLF also adds two bytes to the reaction stream, which is that the browser does not need to be rendered on the page. Everything to format good HTML is to make your competitors easier to read your HTML source code and understand your design.</p> <p>Connect a continuous response.write into a separate statement</p> <p>Do not consider the test of our previous packaging function, the next logical step is to extract all the strings from a separate response.write statement, connect them into a separate statement, which reduces the number of functions It greatly improves the performance of the page.</p> <p>...</p> <p>Response.write ("<HTML>" & _</p> <p>"<head>" & _</p> <p><title> Response Test </ Title> "& _</p> <p></ head> "& _</p> <p>"<body>" & _</p> <p><H1> Response Test </ h1> "& _</p> <p><Table> &_</p> <p><Tr> <TD> <B> First Name: </ b> </ td> <TD> "& firstname &" </ td> </ TR> "& _</p> <p>...</p> <p>"<tr> <td> <b> Birth Date: </ b> </ td> <td>" & birthdate & "</ td> </ tr>"</p> <p></ table> "& _</p> <p></ body> "& _</p> <p>"</ html>")</p> <p>/App1/response3.asp fragment</p> <p>Previous best (reaction speed) = 8.08 msec / PAGE reaction time = 7.05 msec / page</p> <p>Difference = -1.03 msec (decrease 12.7%)</p> <p>Currently, this is the optimized configuration.</p> <p>Connect a continuous response.write into a separate statement, add a CRLF at the end of each line</p> <p>Considering those who require their source code from browsers to see very purely, I use VBCRLF constants in the end of each row in front test, then re-run.</p> <p>...</p> <p>Response.write ("<HTML>" & VBCRLF & _</p> <p>"<head>" & vbcrlf & _</p> <p>"<title> Response Test </ Title>" & VBCRLF & _</p> <p></ head> "& vbcrlf & _</p> <p>...</p> <p>/App1/Response5.asp fragment</p> <p>The best (reaction speed) = 7.05 msec / page</p> <p>Response time = 7.63 msec / page</p> <p>Difference = 0.58 msec (increasing 8.5%)</p> <p>The results of operation have a little reduced performance, which may be due to additional series and increased characters.</p> <p>Review and observation</p> <p>Some rules can be obtained from the previous test of the ASP output:</p> <p>* Avoid excessive use of inline ASP.</p> <p>* Always connect a continuous response.write statement to a separate statement.</p> <p>* Never use the package function around Response.Write to attach CRLF.</p> <p>* If you must format the HTML output, CRLF is added directly within the Response.write statement.</p> <p>Should it turn on the buffer? Start the buffer through the script program</p> <p>The top of the ASP script contains response.buffer = true, IIS caches the contents of the page.</p> <p><% OPTION Explicit</p> <p>Response.buffer = TRUE</p> <p>DIM FIRSTNAME</p> <p>...</p> <p>/App1/buffer__1.asp fragment</p> <p>Previous best (reaction time) = 7.05 msec / page</p> <p>Reaction time = 6.08 msec / page</p> <p>Difference = -0.97 msec (13.7%)</p> <p>Performance has been greatly improved. But wait, it can be better.</p> <p>Start buffer by server configuration</p> <p>Although the buffer in IIS 5.0 is started by default, it must also be manually started in IIS 4.0. At this time, you should find the Properties dialog of the site, where, select the configuration button from the Home Directory tab. Then select "Enable Buffering" under "App Options". For this test, the Response.buffer statement is removed from the script.</p> <p>Previous best = 7.05 msec / page</p> <p>Reaction time = 5.57 msec / page</p> <p>Difference = -1.48 msec (decrease 21.0%)</p> <p>Currently, this is the fastest response we have gotten, more than 21% of the reaction time we have before. From now on, we will test this reaction time as a reference value.</p> <p>Review and observation</p> <p>The buffer is a good way to improve performance, so it is necessary to set the buffer to the server. If some reason, the page does not correctly run the buffer, only the response.buffer = false command can be required. One disadvantage of the buffer is that the user can't see anything from the server before processing the entire page. Therefore, during the processing of complex pages, even if the response.flush to update the user is a good idea. Now there is an additional one in our rules: Always set the buffer through the server.</p> <p>Should I consider adding comments to the ASP code? Most HTML developers know that HTML comments are not a good idea, first increase the size of the transferred data, followed by providing information about the information about your page organizations to other developers. But what is the comment on the ASP page? They never leave the server, but it is also necessary to increase the size of the page, so you must decompose with ASP.</p> <p>In this test, we increase 20 annotations, with 80 characters each, a total of 1600 characters.</p> <p><% OPTION Explicit</p> <p>'------------------------------------- ------------------------------</p> <p>... 20 LINES ...</p> <p>'------------------------------------- ------------------------------</p> <p>DIM FIRSTNAME</p> <p>...</p> <p>/App2/comment_1.asp fragment</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 5.58 msec / page</p> <p>Difference = 0.01 msec (add 0.1%)</p> <p>The result of the test is amazing. Although notes are almost twice that of the document itself, their existence does not have a big impact on the reaction time. So we can follow the following rules:</p> <p>As long as the mode is modeled, the ASP annotation has little effect on performance or does not affect.</p> <p>Should you explicitly set the default language for the page? IIS Processing VBScript is the default setting, but I see that in most examples or <% @Language = VBScript%> declaration to explicitly set the language to VBScript. Our next test will test the presence of this statement impact on performance.</p> <p><% @ Language = VBScript%></p> <p><% OPTION Explicit</p> <p>DIM FIRSTNAME</p> <p>...</p> <p>/App2/language1.asp fragment.</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Response time = 5.64 msec / page</p> <p>Difference = 0.07 msec (increasing 1.2%)</p> <p>It can be seen that there is a slight impact on performance in the statement. therefore:</p> <p>* Set the server's default language configuration to match the language used on the site.</p> <p>* Do not set language statements unless you use non-default languages.</p> <p>If you don't need it, should I close the Sems status? Avoid using IIS's session contexts have many reasons, those already able to be an article independently. The problem we try to answer now is that when the page does not need, close the session context is helpful. In theory, it should be affirmed, because this will not need to use the page to exempt the session context.</p> <p>Like the buffer, there are two configuration methods: through scripts and through server settings.</p> <p>Close the session context through script</p> <p>For this test, you want to close the session context in the page, I add a session status declaration.</p> <p><% @ EnablesessionState = false%> <% Option Explicit</p> <p>DIM FIRSTNAME</p> <p>...</p> <p>/App2/session_1.asp fragment.</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 5.46 msec / page</p> <p>Difference = -0.11 msec (2.0%)</p> <p>Just through such a small effort has been a good progress. Now look at the second part.</p> <p>Close the session context through the server configuration</p> <p>To close the session context on the server, go to the Properties dialog of the site. Select the Configuration button on the Home Directory tab. Then, "Enable Session State" is then canceled under "App Options". We run test without EnablesessionState declaration.</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 5.14 msec / page</p> <p>Difference = -0.43 msec (reduced 7.7%)</p> <p>This is another significant increase in performance. So, our rules should be: Close the SESSION state at the level of the page or application is always in the case of unnecessary.</p> <p>Will the performance have substantive changes in the performance of Option Explicit? Set Option Explicit at the top of an ASP page to require all variables to be declared on the page before use. There are two reasons. First, the application can handle the access to the variable faster. Second, this can prevent the name of our unintentional use of variables. In this test we remove the DIM declaration of Option Explicit references and variables.</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 6.12 msec / page</p> <p>Difference = 0.55 msec (9.8% increase),</p> <p>Although there are some code lines remove from the page, the reaction time is still increased. So, although the Option Explicit is sometimes time, it has a significant effect on performance. So we can add a rule: Option Explicit is always used in VBScript.</p> <p>Will the script logic in a subroutine and a function area? To organize and manage code with functions and subroutines is a good method, especially when a code area is used multiple times in the page. The disadvantage is to add an additional function call to the same work on the system. Another problem with the subroutine and function is the range of variables. Theoretically, the specified variable is more effective in a function area. Now let's take a look at how these two areas.</p> <p>Move the Response.Write statement into a subroutine</p> <p>This test just moves the Response.Write statement into a subroutine area.</p> <p>...</p> <p>Call WriteTable ()</p> <p>Sub WriteTable ()</p> <p>Response.write ("<HTML>" & _</p> <p>"<head>" & _</p> <p>...</p> <p><Tr> <TD> <B> Email: </ b> </ td> <TD> "& email &" </ td> </ tr> "</p> <p>"<tr> <td> <b> Birth Date: </ b> </ td> <td>" & birthdate & "</ td> </ tr>"</p> <p></ table> "& _</p> <p></ body> "& _</p> <p>"</ html>") End Sub</p> <p>/App2/function1.asp fragment</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 6.02 msec / page</p> <p>Difference = 0.45 msec (8.1% increase)</p> <p>As expected, subroutine calls bring additional burden to the page.</p> <p>Move all scripts into subroutines</p> <p>In this test, the response.write statement and variable declarations are moved into a subroutine area.</p> <p><% OPTION Explicit</p> <p>Call WriteTable ()</p> <p>Sub WriteTable ()</p> <p>DIM FIRSTNAME</p> <p>...</p> <p>Dim Birthdate</p> <p>Firstname = "john"</p> <p>...</p> <p>Birthdate = "1/1/1950"</p> <p>Response.write ("<HTML>" & _</p> <p>"<head>" & _</p> <p><title> Response Test </ Title> "& _</p> <p></ head> "& _</p> <p>"<body>" & _</p> <p><H1> Response Test </ h1> "& _</p> <p><Table> &_</p> <p><Tr> <TD> <B> First Name: </ b> </ td> <TD> "& firstname &" </ td> </ TR> "& _</p> <p>...</p> <p>"<tr> <td> <b> Birth Date: </ b> </ td> <td>" & birthdate & "</ td> </ tr>"</p> <p></ table> "& _</p> <p></ body> "& _</p> <p>"</ html>")</p> <p>End Sub</p> <p>/App2/function2.asp fragment</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 5.22 msec / page</p> <p>Difference = -0.35 msec (6.3% decrease)</p> <p>very interesting! Although an additional function call is added to the function range, it is actually improved. We can add the following rules:</p> <p>* On a page, if the code is used more than one, the code is entered into the function area.</p> <p>* Move the variable declaration to the function range for appropriate time.</p> <p>What is the impact of using the included file? An important feature of ASP programming is to include code from other pages. With this feature, the programmer can share a function on multiple pages, making the code easier to maintain. A disadvantage is that the server must assemble the page from multiple sources. The following is two tests using the include file.</p> <p>Use an Include file using inline code</p> <p>In this test, a small code is moved to an incrude file:</p> <p><% OPTION Explicit</p> <p>DIM FIRSTNAME</p> <p>...</p> <p>Dim Birthdate</p> <p>Firstname = "john"</p> <p>...</p> <p>Birthdate = "1/1/1950"</p> <p>%></p> <p><! - #include file = "inc1.asp" -> /app2/include_1.asp fragment</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 5.93 msec / page</p> <p>Difference = 0.36 msec (6.5% increase)</p> <p>This is not surprising. The load is formed using the include file.</p> <p>Use the include file in the function area</p> <p>Here, the code is wrapped in a subroutine in an Include file. The include reference is performed on the top of the page, and the appropriate position adjustment subroutine at the ASP script.</p> <p><% OPTION Explicit</p> <p>DIM FIRSTNAME</p> <p>...</p> <p>Dim Birthdate</p> <p>Firstname = "john"</p> <p>...</p> <p>Birthdate = "1/1/1950"</p> <p>Call WriteTable ()</p> <p>%></p> <p><! - #nclude file = "inc2.asp" -></p> <p>/App2/include_2.asp fragment</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 6.08 msec / page</p> <p>Difference = 0.51 msec (9.2% increase)</p> <p>This affects the effects of performance than the functions call. So: only use the include file when the code is shared between the page.</p> <p>How much load is formed when performing error processing? For all real applications, error handling is necessary. In this test, the error handle is called by calling the ON ERROR RESUME NEXT function.</p> <p><% OPTION Explicit</p> <p>ON Error ResMe next</p> <p>DIM FIRSTNAME</p> <p>...</p> <p>/app2/error_1.asp fragment</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 5.67 msec / page</p> <p>Difference = 0.10 msec (1.8% increase)</p> <p>You can see that the error handle brings a price. We can make the following suggestions: The error handle is used only when there is a situation outside the test or control. One of the most basic examples is to use COM objects such as ADO or FileSystem objects.</p> <p>Set whether a context process has an impact on performance? When the error occurs, set a context handle on the page allows the script to reverse operation. This is set by using the processing declaration on the page.</p> <p><% @ Transaction = Required%></p> <p><% OPTION Explicit</p> <p>DIM FIRSTNAME</p> <p>...</p> <p>/app2/transact1.asp fragment</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 13.39 msec / page</p> <p>Difference = 7.82 msec (140.4% increase)</p> <p>what! This is true and most dramatic. So please pay attention to the following rules: The processing context is used only when two or more operations are performed as a unit.</p> <p>Conclusion The importance of the first part of this article is the accumulation of many small things. In order to emphasize this problem, I set up the last test, in which we have used all the operations that have previously tested but actually have a bad impact. I contain many response.write declarations, turn off the buffer, set the default language, remove the Option Explicit reference and initialize the error handle.</p> <p><% @ Language = VBScript%></p> <p><%</p> <p>ON Error ResMe next</p> <p>Firstname = "john"</p> <p>...</p> <p>Birthdate = "1/1/1950"</p> <p>Response.write ("<HTML>") Response.write ("<HEAD>")</p> <p>Response.write ("<title>")</p> <p>Response.write ("</ head>")</p> <p>Response.write ("<body>")</p> <p>Response.write ("<H1> Response Test </ h1>")</p> <p>Response.write ("<Table>")</p> <p>Response.write ("<tr> <td> <b> first name: </ b> </ td> <td>" & numbertname & "</ td> </ tr>")</p> <p>...</p> <p>Response.write ("<tr> <td> <b> Birth Date: </ b> </ td> <td>" & birthdate & "</ td> </ tr>")</p> <p>Response.write ("</ Table>")</p> <p>Response.write ("</ Body>")</p> <p>Response.write ("</ html>")</p> <p>%></p> <p>/App2/final_1.asp fragment</p> <p>Benchmark = 5.57 MSEC / PAGE</p> <p>Reaction time = 8.85 msec / page</p> <p>Difference = 3.28 msec (58.9% increase)</p> <p>It may be obvious, but it is more important, that is, the code we placed on the page will affect performance. Small changes on the page sometimes greatly increase the reaction time.</p> <p>Rule summary * Avoid excessive use of inline ASP.</p> <p>* Always connect a continuous response.write statement to a separate statement.</p> <p>* Never use the package function to add CRLF around Response.Write.</p> <p>* If you must format the HTML output, CRLF is added directly within the Response.write statement.</p> <p>* Always set the buffer through the server.</p> <p>* As long as mode of use, the ASP annotation has little effect on performance or no effect.</p> <p>* Set the server's default language configuration to match the language used on the site.</p> <p>* Do not set language statements unless you use non-default languages.</p> <p>* Always use Option Explicit in VBScript.</p> <p>* Close the session status at the level of the page or application is always in the case of not needed.</p> <p>* Use the include file only when the code is shared between the page.</p> <p>* On a page, if the code is used more than one, the code is entered into the function area.</p> <p>* Move the variable declaration to the function range for appropriate time.</p> <p>* The error handle is used only when the test or control capability occurs.</p> <p>* The context processing is only used when two or more operations are performed as a unit.</p> <p>Review now, there are many problems that can be used as a general policy:</p> <p>* Avoid redundancy - do not set the properties that have been set by default.</p> <p>* Limit the number of times the function call.</p> <p>* Reduce the scope of the code.</p> <p>In the second part of this article, we will explore some in-depth issues related to ADO and COM objects.</p> <p>In the first part of this article, I review some basic issues related to ASP development, introduced some of the results of performance testing to understand what the code we placed on the page may affect the operation performance. In this series of second part, we will explore the most extensive use of the armed ASP, namely, using the database content through the ActiveX Data Object (ADO). ADO is a Microsoft universal and simple database interface. ADO has a lot of functional settings, so the biggest challenge when preparing this article is to limit the scope of the test problem. Considering that reading a big load is applied to the web server, I decided to limit the contents of the study to find the optimized configuration for using the ADO record set. But this restriction has put forward a challenge because ADO provides a variety of ways to perform the same function. For example, the record set can be recovered from the Recordset class or recover from the Connection and Command classes. In addition, once you have a recordset, there are many options that will dramatically affect performance. Therefore, like the first part, I will involve some specific problems as much as possible.</p> <p>The purpose of my research is to get enough information to find the answer to the following questions:</p> <p>* Do you should use the adovbs.inc containing files?</p> <p>* Do you have a separate Connection object when you use a recordset?</p> <p>* What is the best way to recover a record set?</p> <p>* In the type of pointer and lock, what is the most effective?</p> <p>* Will you use a disconnected recordset?</p> <p>* What is the best way to set up a record set (RECORDSET) attribute?</p> <p>* What is the most effective way to reference record concentration domain values?</p> <p>* Can I use a temporary string to replace the buffer?</p> <p>How is the test set up? For testing in this study, we share 21 ASP pages (included in this article download content). Each page is configured to return to record sets with 3 different queries, which are 0, 25, 250 records in these records. This helps us isolate the problem of loading records and performance issues on record concentration cycles.</p> <p>To meet these changes, database connection strings and test SQL strings are stored as application variables in Global.asa. Because our test database is running on Microsoft SQL Server 7.0, our connection string specifies OLEDB as a connection vendor, the Northwind sample database (included in the SQL server) as the current database. The SQL SELECT statement requires 7 specific domains in the Northwind ORDERS table.</p> <p><Script language = vbscript runat = server></p> <p>SUB Application_onstart</p> <p>Application ("conn") = "provider = sqloledb;" & _</p> <p>"Server = myserver;" & _</p> <p>"UID = sa;" & _</p> <p>"pwd =;" & _</p> <p>"Database = northwind"</p> <p>Application ("SQL") = "SELECT TOP 0 ORDERID," & _</p> <p>"Customerid," & _</p> <p>Employeeid, "& _</p> <p>"ORDERDATE," & _</p> <p>"RequiredDate," & _</p> <p>ShippedDate, "& _</p> <p>"FREIGHT" & _</p> <p>"From [orderers]"</p> <p>End Sub</p> <p></ Script></p> <p>'Alternate SQL? 25 Records</p> <p>Application ("SQL") = "SELECT TOP 25 ORDERID," & _</p> <p>"Customerid," & _</p> <p>Employeeid, "& _</p> <p>"ORDERDATE," & _</p> <p>"RequiredDate," & _</p> <p>ShippedDate, "& _</p> <p>"FREIGHT" & _</p> <p>"From [orderers]"</p> <p>'Alternate SQL? 250 Records</p> <p>Application ("SQL") = "SELECT TOP 250 ORDERID," & _</p> <p>"Customerid," & _</p> <p>Employeeid, "& _</p> <p>"ORDERDATE," & _</p> <p>"RequiredDate," & _</p> <p>ShippedDate, "& _</p> <p>"FREIGHT" & _</p> <p>"From [orderers]"</p> <p>Our test server is a double 450 MHz Pentium, 512MB RAM, running NT Server 4.0 SP5, MDAC 2.1 (Data Access Components), and version 5.0 of Microsoft Scripting Engine. The SQL server runs on a separate machine of the same specification. Like the first article, I use Microsoft's Web Application Key Tool Record from the initial page request to the last byte (TTLB) time, accurate to milliseconds on the server. This test script runs 20 hours and calls more than 1,300 pages. The displayed time is the average TTLB of the session. To remember, the same as the first article, we just try to involve performance, rather than scalability and capacity issues.</p> <p>Please note that we open the buffer on the server. In addition, I set all the file names as the same length, so there will be one or more underlined liners in the file name.</p> <p>Started in the first test, we use typical scenes in the typical Microsoft ASP ADO sample file to restore a simple recordset. In this example (ADO__01.asp), we first create a Connection object and create a Recordset object. Of course, I have made some modifications in the script to reflect some good practices involved in the first part of this series.</p> <p><% OPTION Explicit%></p> <p><! - #nclude file = "adovbs.inc" -></p> <p><%</p> <p>DIM Objconn</p> <p>DIM OBJRS</p> <p>Response.write (_</p> <p>"<Html> <head>" & _</p> <p><Title> ADO TEST </ Title> "& _</p> <p>"</ Head> <body>" _</p> <p>)</p> <p>Set objconn = server.createObject ("adoDb.connection")</p> <p>Objconn.open Application ("conn")</p> <p>Set objrs = server.createObject ("AdoDb.Recordset") objrs.activeconnection = Objconn</p> <p>Objrs.cursortype = adopenforwardonly</p> <p>Objrs.lockType = AdlockReadOnly</p> <p>Objrs.open Application ("SQL")</p> <p>IF objrs.eof kil</p> <p>Response.write ("No Records Found")</p> <p>Else</p> <p>'Write Headings</p> <p>Response.write (_</p> <p>"<Table border = 1>" & _</p> <p><TR> "& _</p> <p>"<Th> ORDERID </ TH>" & _</p> <p>"<TH> Customerid </ TH>" & _</p> <p>"<TH> Employeeid </ TH>" & _</p> <p>"<TH> ORDERDATE </ TH>" & _</p> <p><TH> RequiredDate </ TH> &_</p> <p>"<TH> ShippedDate </ TH>" & _</p> <p>"<Th> Freight </ TH>" & _</p> <p></ Tr> "_</p> <p>)</p> <p>'Write Data</p> <p>Do While Not Objrs.eof</p> <p>Response.write (_</p> <p><TR> "& _</p> <p>"<TD>" & objrs ("ORDERID") & "</ TD>" & _</p> <p>"<TD>" & objrs ("Customerid") & "</ TD>" & _</p> <p>"<TD>" & objrs ("EMPLOYEEID") & "</ td>" & _</p> <p>"<TD>" & objrs ("ORDERDATE") & "</ TD>" & _</p> <p>"<TD>" & objrs ("RequiredDate") & "</ td>" & _</p> <p>"<TD>" & objrs ("ShippedDate") & "</ td>" & _</p> <p>"<TD>" & objrs ("freight") & "</ td>" & _</p> <p></ Tr> "_</p> <p>)</p> <p>Objrs.movenext</p> <p>Loop</p> <p>Response.write ("</ Table>")</p> <p>END IF</p> <p>Objrs.close</p> <p>Objconn.close</p> <p>Set objrs = Nothing</p> <p>Set objconn = NothingResponse.write ("</ body> </ html>")</p> <p>%></p> <p>The result is this:</p> <p>Let's first take a look at what the numbers in each column are:</p> <p>0 The representative runs the TTLB when returning 0 records, unit milliseconds. In all we test, this number is used to log the page's load or load page to create objects but not in the data cycle.</p> <p>25 Load and display 25 recorded TTLB (ms).</p> <p>Tot Time / 25 TTLB is divided by 25 records (ms). Represents the total average time of each record.</p> <p>The DISP TIME / 25 subtracts the TTLB of the "0" in the TTLB of milliseconds, and divides 25 records. Represents the time of each record in the recordset cycle.</p> <p>250 Load and display 250 recorded TTLB (ms).</p> <p>TOT TIME / 250 TTLB divided by 250 records (ms). Represents the total average time of each record.</p> <p>The DISP TIME / 250 subtracts the TTLB of the "0" in the TTLB of milliseconds, and divides 250 records. Represents the time of each record in the recordset cycle.</p> <p>We will compare these values ​​with the results below.</p> <p>Should I use the adovbs.inc containing files? I want to solve this problem. The Adovbs.inc file provided by Microsoft contains 270 line code that represents most of the constants that can be applied to the ADO properties. In our example, only 2 of this file in this file. So for this test (ADO__02.asp), I canceled the reference to the file, and the actual number in the attribute list is used instead of constants.</p> <p>Objrs.cursortype = 0 'AdopenForwardonly</p> <p>Objrs.lockType = 1 'AdlockReadOnly</p> <p>We can see that the load time is reduced by 23%. This is different from the display time of each record, as this change should not have an impact on the recording concentration cycle. There are several solutions to this issue. I recommend using the adovbs.inc file as a reference, if necessary, use the annotation to indicate the number. To remember, just like in the first part, the annotation does not require fear, because as long as the mode is moderate, they do not have a big impact on performance. Another way is to copy only the constant you need from the file to the page.</p> <p>Solving this problem has a cool way to connect all ADO constants to your application by connecting the ADO class library to your application. Add the following code to your global.asa file, you can use all constants directly.</p> <p><! - metadata type = "typeelib"</p> <p>File = "C: / Program files / compon files / system / ado / msado15.dll"</p> <p>Name = "AdoDb Type Library" -></p> <p>or</p> <p><! - metadata type = "typeelib"</p> <p>UUID = "00000205-0000-0010-8000-00Aa006d2ea4"</p> <p>Name = "AdoDb Type Library" -></p> <p>So, here is our first rule:</p> <p>* Avoid including an adovbs.inc file, use constants with other methods.</p> <p>When using a recordset, should a separate Connection object? If you want to answer this question correctly, you need to verify the test results in two different situations: The first is to perform a database processing per page, the second is Pages perform multiple database processing.</p> <p>In the previous example, we have created a separate connection object and passed it to the ActiveConnection property of the recordset. However, it is also possible to only pass the connection string to this property, so that an additional step is to be avoided, that is, a separate component is illustrated and configured in the script (ADO__03.asp): objrs.activeConnection = Application ("conn")</p> <p>Although we still created a connection in the recordset, it was created with very optimized, so we saw that the startup time was reduced by 23% higher than the previous test, as expected, each There is little difference in the display time of the record.</p> <p>Therefore, our second rules are:</p> <p>* When a single recordset is used, the connection string is passed to the ActiveConnection property.</p> <p>Below you want to determine if multiple record sets are created on a page, this logic is still established. To test this situation, I introduced the For loop and repeated the previous example 10 times. In this test, we will also study 3 choices:</p> <p>First, we created and destroy the Connection object in each loop (ADO__04.ASP):</p> <p>DIM I</p> <p>FOR i = 1 to 10</p> <p>Set objconn = server.createObject ("adoDb.connection")</p> <p>Objconn.open Application ("conn")</p> <p>Set objrs = server.createObject ("adoDb.recordset")</p> <p>Objrs.activeConnection = Objconn</p> <p>Objrs.cursortype = 0 'AdopenForwardonly</p> <p>Objrs.lockType = 1 'AdlockReadOnly</p> <p>Objrs.open Application ("SQL")</p> <p>IF objrs.eof kil</p> <p>Response.write ("No Records Found")</p> <p>Else</p> <p>'Write Headings</p> <p>...</p> <p>'Write Data</p> <p>...</p> <p>END IF</p> <p>Objrs.close</p> <p>Set objrs = Nothing</p> <p>Objconn.close</p> <p>Set objconn = Nothing</p> <p>NEXT</p> <p>Second, create a separate Connection object in the loop and share it with each recordset (ADO__05.ASP):</p> <p>Set objconn = server.createObject ("adoDb.connection")</p> <p>Objconn.open Application ("conn")</p> <p>DIM I</p> <p>FOR i = 1 to 10</p> <p>Set objrs = server.createObject ("adoDb.recordset")</p> <p>Objrs.activeConnection = Objconn</p> <p>Objrs.cursortype = 0 'AdopenForwardonly</p> <p>Objrs.lockType = 1 'AdlockReadOnly</p> <p>Objrs.open Application ("SQL")</p> <p>IF objrs.eof kil</p> <p>Response.write ("No Records Found")</p> <p>Else</p> <p>'Write Headings</p> <p>...</p> <p>'Write Data</p> <p>...</p> <p>END IF</p> <p>Objrs.closset objrs = Nothing</p> <p>NEXT</p> <p>Objconn.close</p> <p>Set objconn = Nothing</p> <p>Third, pass the connection string to the ActiveConnection property (ADO__06.ASP) in each loop:</p> <p>DIM I</p> <p>FOR i = 1 to 10</p> <p>Set objrs = server.createObject ("adoDb.recordset")</p> <p>Objrs.activeConnection = Application ("conn")</p> <p>Objrs.cursortype = 0 'AdopenForwardonly</p> <p>Objrs.lockType = 1 'AdlockReadOnly</p> <p>Objrs.open Application ("SQL")</p> <p>IF objrs.eof kil</p> <p>Response.write ("No Records Found")</p> <p>Else</p> <p>'Write Headings</p> <p>...</p> <p>'Write Data</p> <p>...</p> <p>END IF</p> <p>Objrs.close</p> <p>Set objrs = Nothing</p> <p>NEXT</p> <p>You may have guessed that it is a low-efficiency method to create and destroy the Connection object in each loop. But amazing is that only the efficiency of transmitting the connection string in each cycle is only a little bit lower than the efficiency of the shared single.</p> <p>Despite this, our third rules are:</p> <p>* When using multiple record sets on a page, create a Connection object and reuse it in the ActiveConnection property.</p> <p>In the type of pointers and locks, which is the most effective? So far, all of our tests use only a pointer for forward only in the recordset. However, ADO also provides three types of pointers for records: Static, Dynamic, and KeySet (keyboard). Each provides additional functions, such as moving and backward movement, and when others are established, you can see the modified function. However, the connotation of these pointer types is not the scope discussed herein. I left these to you. Below is a comparative analysis of various types.</p> <p>These additional pointers have significantly caused a larger load (ADO__03.asp) compared to their similar Forward Only. In addition, these pointers are slower during cycle. I want to share with you to avoid this idea: "I need a Dynamic pointer from time to time, so simply use it."</p> <p>In essence, the same problem is also applicable to the type of lock. Only the READ ONLY type lock is only used in the previous test. However, there are three types of locks: Lock Pessimistic, Lock Optimistic and Lock Batch Optimistic. Like the choice of pointers, these locks also provide additional functions and controls for data in the processing record set. Similarly, I will give you myself for you to learn the appropriate use of each lock setting.</p> <p>So guiding us to consider the logic of rule 4 very simple: using the simplest pointer and lock of the task that best suits you.</p> <p>What is the best way to get a record set? So far, we just recover records through the Recordset object. But ADO also provides some indirect methods for acquiring records. The next test compares the values ​​in the ADO__03.asp to create a recordset object directly from a Connection object (conn_01.asp).</p> <p>Set objconn = server.createObject ("adoDb.connection") Objconn.open Application ("conn")</p> <p>Set objrs = Objconn.execute (Application ("SQL"))</p> <p>We see that there is a slight increase in the load that shows that the time of each record has not changed.</p> <p>Then, let's take a look at a RecordSet object directly from a Command object (CMD__01.asp):</p> <p>Set objcmd = server.createObject ("adoDb.command")</p> <p>Objcmd.activeConnection = Application ("conn")</p> <p>Objcmd.commandtext = Application ("SQL")</p> <p>Set objrs = Objcmd.execute</p> <p>We once again see a slight increase in the load, and the display time of each record has a nominal difference. Although the last two methods have little effect on performance, there is a big problem that needs to be considered.</p> <p>Creating a recordset via the Recordset class For control how to handle the record set provides maximum flexibility. Although other methods have not proposed an overwhelming performance problem, you will be confused by the default states and lock types, which are not necessarily optimal for your specific needs.</p> <p>So, unless you need other methods because of some special reason you need other methods: Examples of the record set to get the best performance and maximum flexibility through the AdoDb.Recordset class.</p> <p>Should I disconnect the record? ADO provides a selection for disconnecting a recordset, and the recording set will resume all data in a forward query, turn off the connection, and use a local (or customer) pointer to move in the data set. This also provides an opportunity for an early release connection. This situation is necessary for processing remote data services, because the data must be disconnected from the database. But is it good for ordinary uses?</p> <p>Below we add the CursorLocation property, turn off the connection after opening the record set (Client1.asp):</p> <p>Set objrs = server.createObject ("adoDb.recordset")</p> <p>Objrs.cursorLocation = 3 'aduseclient</p> <p>Objrs.activeConnection = Application ("conn")</p> <p>Objrs.lockType = 1 'AdlockReadOnly</p> <p>Objrs.open Application ("SQL")</p> <p>Objrs.activeConnection = Nothing</p> <p>In theory, this technology should lead to faster performance. There are two reasons: First, when moving in the recordset, avoiding the repeated request by the connection; secondly cancel the connection to reduce the resource requirements. However, when using the client pointer, the efficiency is low. May be due to the use of the customer pointer position, no matter what your settings, Cursortype is modified to static.</p> <p>Rules 6 is this: unless it is required in an open environment, avoiding disconnects.</p> <p>What is the best way to set up recordset properties? All of the previous tests are set directly to the properties of the record set through separate attribute settings. But the RecordSet.open function can receive additional parameters for all properties we need. Although for each attribute, separate code lines are readily read and maintained, they still have to perform a single function call, must be set through the COM interface (ADO__07.asp): set objrs = server.createObject ("adoDb.recordset ")</p> <p>Objrs.open Application ("SQL"), Application ("Conn"), 0, 1</p> <p>'Adforwardonly, AdlockReadonly</p> <p>These methods have brought the difference in the load, so we get rules 7: Do not worry about the set record set attributes separately</p> <p>What is the most effective way to reference record concentration domain values? So far, I use the name of the recordset in the name of the name. This may be a very low efficiency, because each call requires a field. To prove this, the following test is to reference the domain by recording a set of sets of concentrated domains (ADO__08.ASP):</p> <p>'Write Data</p> <p>Do While Not Objrs.eof</p> <p>Response.write (_</p> <p><TR> "& _</p> <p><TD> & Objrs (0) & "</ TD>" & _</p> <p><TD> & Objrs (1) & "</ TD>" & _</p> <p><TD> & Objrs (2) & "</ TD>" & _</p> <p><TD> & Objrs (3) & "</ TD>" & _</p> <p>"<TD>" & objrs (4) & "</ td>" & _</p> <p>"<TD>" & objrs (5) & "</ td>" & _</p> <p>"<TD>" & objrs (6) & "</ td>" & _</p> <p></ Tr> "_</p> <p>)</p> <p>Objrs.movenext</p> <p>Loop</p> <p>As we expected, the load time varies small (differences may be caused by slight reduction on the code). But this technology has brought a significant reduction in effective display time.</p> <p>In the following example, we will specify a separate variable for each domain. This approach avoids all findings in the table cycle (ADO__09.ASP):</p> <p>IF objrs.eof kil</p> <p>Response.write ("No Records Found")</p> <p>Else</p> <p>'Write Headings</p> <p>...</p> <p>DIM FLD0</p> <p>DIM FLD1</p> <p>DIM FLD2</p> <p>DIM FLD3</p> <p>DIM FLD4</p> <p>DIM FLD5</p> <p>DIM FLD6</p> <p>Set Fld0 = ObJRS (0)</p> <p>Set Fld1 = Objrs (1)</p> <p>Set Fld2 = ObJRS (2)</p> <p>Set Fld3 = ObJRS (3)</p> <p>SET FLD4 = ObJRS (4)</p> <p>SET FLD5 = ObJRS (5)</p> <p>Set Fld6 = ObJRS (6)</p> <p>'Write DataDo While Not Objrs.eof</p> <p>Response.write (_</p> <p><TR> "& _</p> <p>"<TD> & FLD0 &" </ TD> "& _</p> <p>"<TD> & FLD1 &" </ TD> "& _</p> <p>"<TD> & FLD2 &" </ TD> "& _</p> <p><TD> & FLD3 & "</ TD>" & "</p> <p><TD> & FLD4 & "</ TD>" & _</p> <p><TD> "& FLD5 &" </ TD> "& _</p> <p>"<TD> & FLD6 &" </ TD> "& _</p> <p></ Tr> "_</p> <p>)</p> <p>Objrs.movenext</p> <p>Loop</p> <p>SET FLD0 = Nothing</p> <p>Set fld1 = Nothing</p> <p>SET FLD2 = Nothing</p> <p>Set Fld3 = Nothing</p> <p>SET FLD4 = Nothing</p> <p>SET FLD5 = Nothing</p> <p>Set fld6 = Nothing</p> <p>Response.write ("</ Table>")</p> <p>END IF</p> <p>By current, the result of this method is the best. The display time of each record will fall into. 45 milliseconds.</p> <p>Now, all test scripts are configured to have some understanding of the results record set. For example, we have been encoded to domain names in the bar title, separately references the values ​​of these domains. The following example provides a dynamic solution that circulates in the collection of domains, not only data, but also gets the domain title (ADO__10.ASP):</p> <p>IF objrs.eof kil</p> <p>Response.write ("No Records Found")</p> <p>Else</p> <p>'Write Headings</p> <p>Response.write ("<Table Border = 1> <TR>")</p> <p>For Each Objfld in Objrs.fields</p> <p>Response.write ("<th>" & objfld.name & "</ tH>")</p> <p>NEXT</p> <p>Response.write ("</ TR>")</p> <p>'Write Data</p> <p>Do While Not Objrs.eof</p> <p>Response.write ("<tr>")</p> <p>For Each Objfld in Objrs.fields</p> <p>Response.write ("<TD>" & objfld.value & "</ td>")</p> <p>NEXT</p> <p>Response.write ("</ TR>")</p> <p>Objrs.movenext</p> <p>Loop</p> <p>Response.write ("</ Table>")</p> <p>END IF</p> <p>It can be seen that we have a loss in performance, but this method is still more faster than ADO__07.asp. The following test is in some folds between the last two tests. By saving the domain in a dynamic allocation array, there is only a dynamic flexibility and some loss of performance is also returned.</p> <p>IF objrs.eof kil</p> <p>Response.write ("No Records Found")</p> <p>Else</p> <p>Dim FldCount</p> <p>Fldcount = Objrs.fields.count</p> <p>DIM FLD ()</p> <p>Redim Fld (FLDCOUNT)</p> <p>DIM I</p> <p>For i = 0 to fldcount-1</p> <p>SET FLD (I) = ObJRS (i)</p> <p>NEXT</p> <p>'Write Headings</p> <p>Response.write ("<Table Border = 1> <TR>")</p> <p>For i = 0 to fldcount-1</p> <p>Response.write ("<TH>" & FLD (i) .Name & "</ TH>")</p> <p>NEXT</p> <p>Response.write ("</ TR>")</p> <p>'Write Data</p> <p>Do While Not Objrs.eof</p> <p>Response.write ("<tr>")</p> <p>For i = 0 to fldcount-1</p> <p>Response.write ("<TD>" & FLD (i) & "</ td>")</p> <p>NEXT</p> <p>Response.write ("</ TR>")</p> <p>Objrs.movenext</p> <p>Loop</p> <p>For i = 0 to fldcount-1</p> <p>Set FLD (i) = Nothing</p> <p>NEXT</p> <p>Response.write ("</ Table>")</p> <p>END IF</p> <p>Although it is not fast than the best value, it is much faster than the previous example, and there is a advantage that it is capable of dynamically expanding any record set.</p> <p>In the next test, we will make a thorough change for the previous solution, create an array of loops using the getRows instruction of the record set, not a loop in the recordset itself. Note that after calling getRows, set the record set to Nothing, so that system resources can be released faster. In addition, pay attention to the first dimension representative domain of the array, the second dimension represents the line (ADO__12.ASP):</p> <p>IF objrs.eof kil</p> <p>Response.write ("No Records Found")</p> <p>Objrs.close</p> <p>Set objrs = Nothing</p> <p>Else</p> <p>'Write Headings</p> <p>...</p> <p>'set array</p> <p>DIM Arrrs</p> <p>Arrrs = objrs.getrows</p> <p>'Close RecordSet Early</p> <p>Objrs.close</p> <p>Set objrs = Nothing</p> <p>'Write Data</p> <p>DIM NumRows</p> <p>DIM Numflds</p> <p>DIM ROW</p> <p>DIM FLD</p> <p>Numflds = ubound (arrrs, 1)</p> <p>Numrows = Ubound (Arrrs, 2)</p> <p>For row = 0 to NumRows</p> <p>Response.write ("<tr>")</p> <p>For fld = 0 to Numflds</p> <p>Response.write ("<TD>" & Arrrs (FLD, ROW) & "</ TD>") Next</p> <p>Response.write ("</ TR>")</p> <p>NEXT</p> <p>Response.write ("</ Table>")</p> <p>END IF</p> <p>By using the getRows directive, you can get the entire recordset and load it into an array. When a particularly large recordset is restored, this method may cause resource problems, but the data is more than much, because the function calls similar to MOVENEXT and EOF detection can be canceled.</p> <p>However, the increase in speed is indeed, because the metadata of the record set is no longer with data. Around this issue, I use the recordset to recover the title name before calling getRows. You can also extract data types and other information in advance. Also note that in our test, performance is only available when using large records.</p> <p>In this part of the final test, let's further use the getString instruction of the record set. This method extracts the entire recordset into a large string, allowing you to specify your own separator (ADO__13.asp):</p> <p>IF objrs.eof kil</p> <p>Response.write ("No Records Found")</p> <p>Objrs.close</p> <p>Set objrs = Nothing</p> <p>Else</p> <p>'Write Headings</p> <p>...</p> <p>'set array</p> <p>DIM STRTABLE</p> <p>Strtable = objrs.getstring (2, "</ td> <td>," </ td> </ tr> <tr> <td> ")</p> <p>'Close RecordSet Early</p> <p>Objrs.close</p> <p>Set objrs = Nothing</p> <p>Response.write (STRTABLE & "</ TD> </ TR> </ Table>")</p> <p>END IF</p> <p>Although this approach is close to the highest level, it is only suitable for the easiest design because it does not apply to the special case of data.</p> <p>Observing the time of performing each record before we started this test, the time is always. 83 milliseconds. Most methods in this set of tests have reduced this number half. Although some methods clearly provide faster speed, the cost is a decrease in flexibility.</p> <p>The following rules are in the order of importance:</p> <p>* When the value in the record set does not need to treat and format it into a unified format, use the getString method to extract data. * When you need more flexibility in design, you don't need to work with metadata of the record set, and extract data into an array using the getRows method. * When you need to design flexibility and metadata, you will constrain your domain in a local variable before entering a loop of a data recovery. Avoid using the name reference domain. Can I use a temporary string to replace the buffer? This is a small diagram caused by some annotations submitted by my last article. The problem to be discussed is to collect output around the use of the buffer and use the temporary string as an alternative, which allows RESPONSE.WRITE to call only once. To test, I started from the ADO_11.asp code, and the result is attached to a string instead of calling Response.Write at each loop. When the entire operation is over, the response.write is called on the string (STR__01) .asp:</p> <p>DIM STRTABLE</p> <p>Strtable = "" 'Write Headings</p> <p>STRTABLE = STRTABLE & "<Table Border = 1> <TR>"</p> <p>For i = 0 to fldcount-1</p> <p>STRTABLE = STRTABLE & "<TH>" & FLD (i) .Name & "</ TH>"</p> <p>NEXT</p> <p>STRTABLE = STRTABLE & "</ TR>"</p> <p>'Write Data</p> <p>Do While Not Objrs.eof</p> <p>STRTABLE = STRTABLE & "<TR>"</p> <p>For i = 0 to fldcount-1</p> <p>STRTABLE = STRTABLE & "<TD>" & FLD (i) & "</ td>"</p> <p>NEXT</p> <p>STRTABLE = STRTABLE & "</ TR>"</p> <p>Objrs.movenext</p> <p>Loop</p> <p>For i = 0 to fldcount-1</p> <p>Set FLD (i) = Nothing</p> <p>NEXT</p> <p>STRTABLE = STRTABLE & "</ TABLE>"</p> <p>Response.write (STRTABLE)</p> <p>It seems that it is not very good. Maybe it's like many people suggested that we should specify some spaces for this string with the space instruction so that it does not need to reassign space for yourself during the cycle (STR__02.asp):</p> <p>DIM STRTABLE</p> <p>STRTABLE = SPACE (10000)</p> <p>Perhaps the Space instruction is not as suggested. Our final rules are: Do not use temporary strings to collect output.</p> <p>Summary of the rules Now let's re-summarize these rules:</p> <p>* Avoid including an adovbs.inc file, use constants with other methods.</p> <p>* When a single recordset is used, the connection string is passed to the ActiveConnection property.</p> <p>* When using multiple record sets on a page, create a Connection object and reuse it in the ActiveConnection property.</p> <p>* Use the simplest pointer and lock of the task that best suits your task.</p> <p>* Exemplary record sets through the AdoDb.Recordset class to get the best performance and maximum flexibility.</p> <p>* Unless it is required in an open environment, avoid using disconnected recording sets.</p> <p>* Do not feel worried about the separate setting record set properties.</p> <p>* When the value in the record set does not need to treat and format it into a unified format, use the getString method to extract data.</p> <p>* When you need more flexibility in design, you don't need to work with metadata of the record set, and extract data into an array using the getRows method.</p> <p>* When you need to design flexibility and metadata, you will constrain your domain in a local variable before entering a loop of a data recovery. Avoid using the name reference domain.</p> <p>* Do not use a temporary string to collect output.</p> <p>Conclusion, the most important point we have learned from these tests is that small changes will have a big impact in performance. If we can see the first test with ADO__09.asp (the fastest result in the recordset cycle), can you see when the reaction? Br></p> <p>So I have to remember, never want to be of course. If you can't affirm, run some targeted tests.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-131074.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="131074" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.056</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'j7BBNXSXbqxkA7itAi_2BimOgLVEr8K0qe07JAicLQbv0dMJMhOWpLSjQmGEUoT4ZzGV4PJWL6fN_2Bks1hC67LNuw_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>