您现在的位置是:网站首页> 编程资料编程资料

asp 性能测试报告 学习asp朋友需要了解的东西_应用技巧_

2023-05-25 285人已围观

简介 asp 性能测试报告 学习asp朋友需要了解的东西_应用技巧_

在服务器上生成动态内容是使用ASP最主要的原因之一,所以我们选择的第一个测试项目是确定把动态内容发送到应答流使用什么方法最好。基本的选择有两种(以及它们的一些变化):使用内嵌ASP标记,使用Response.Write语句。

   为测试这些不同的方法,我们创建了一个简单的ASP页面,页面先定义一些变量然后把它们插入到表格。虽然这个页面很简单,而且没有实际用途,但它足以让我们分离和测试各个问题。

   2.1 使用ASP内嵌标记

   第一个测试是使用ASP的内嵌标记<%= x %>,其中x是一个变量。这是使用最方便的方法,而且它可以让页面的HTML部分变得更容易阅读和维护。
复制代码 代码如下:

<% OPTION EXPLICIT
Dim FirstName
Dim LastName
Dim MiddleInitial
Dim Address
Dim City
Dim State
Dim PhoneNumber
Dim 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><br></HEAD><br><BODY><br><H1>Response Test</H1><br><TABLE><br><tr><td><b>First Name:</b></td><td><%= FirstName %></td></tr><br><tr><td><b>Middle Initial:</b></td><td><%= MiddleInitial %></td></tr><br><tr><td><b>Last Name:</b></td><td><%= LastName %></td></tr><br><tr><td><b>Address:</b></td><td><%= Address %></td></tr><br><tr><td><b>City:</b></td><td><%= City %></td></tr><br><tr><td><b>State:</b></td><td><%= State %></td></tr><br><tr><td><b>Phone Number:</b></td><td><%= PhoneNumber %></td></tr><br><tr><td><b>Fax Number:</b></td><td><%= FaxNumber %></td></tr><br><tr><td><b>EMail:</b></td><td><%= EMail %></td></tr><br><tr><td><b>Birth Date:</b></td><td><%= BirthDate %></td></tr><br></TABLE><br></BODY><br></HTML><br></div><br>/app1/response1.asp的完整代码 <br><br>最好记录 = 8.28 毫秒/页 <br><br><br><br><br>   2.2 使用Response.Write输出每一行HTML代码 <br><br>   许多优秀的文献指出,应当避免使用前面的内嵌标记方法,因为它导致一个称为“上下文切换”的操作。这个操作发生在Web服务器所处理的代码类型发生变化的时候(从纯HTML的发送到脚本处理,或反过来),这种切换需要一定的时间。许多程序员在了解了这一点之后,他们的第一个反应是将每一行HTML代码都用Response.Write函数来输出: <br><div class="codetitle"><span><a data="77069" class="copybut" id="copybut77069"><u>复制代码</u></a></span> 代码如下:</div><div class="codebody" id="code77069"><br>... <br>Response.Write("<html>") <br>Response.Write("<head>") <br>Response.Write(" <title>Response Test")
Response.Write("")
Response.Write("")
Response.Write("

Response Test

")
Response.Write("")
Response.Write("")
Response.Write("")
...

/app1/response2.asp片断

最好记录 = 8.28 毫秒/页
响应时间 = 8.08 毫秒/页
差  额 = -0.20 毫秒 (减少 2.4%)




   和内嵌标记版本相比,我们所看到的性能改善非常小,简直令人惊讶。这或许是因为页面中多出了许多函数调用。不过这种方法还有一个更大的缺点,由于HTML代码嵌入到了函数内,脚本代码变得非常冗长,阅读和维护都不方便。

   2.3 使用封装函数

   Response.Write并不会在文本行的末尾加上CRLF(Carriage Return - Line Feed,回车换行),这是使用上面这种方法最令人失望的地方。尽管已经在服务器端把HTML代码作了很好的格式化,但在浏览器中看到的仍旧只有长长的一行代码。不过失望的不仅是这一个问题,人们很快就发现不存在能够自动添加CRLF的Response.WriteLn函数。一个很自然的反应就是创建Response.Write的封装函数,在每行的后面加上CRLF:
...
writeCR("")
...
SUB writeCR(str)
Response.Write(str & vbCRLF)
END SUB
/app1/response4.asp片断

最好记录 = 8.08 毫秒/页
响应时间 = 10.11 毫秒/页
差  额 = +2.03 毫秒 (增加 25.1%)




   结果是性能的大大下降。当然,这主要是因为这种方法使得函数的调用次数加倍,它对性能的影响非常明显。应当不惜代价地避免这种用法,CRLF导致每行的末尾多了两个字节,而这两个字节对于浏览器显示页面是没有用的。在大多数情况下,浏览器端HTML代码的格式美观只是方便了你的竞争者阅读和理解页面的设计。

   2.4 合并多个Response.Write

   如果不考虑最后一次有关封装函数的测试,下一个合理的步骤应当是将所有字符串从分开的Response.Write语句合并到一个语句,从而减少函数调用次数、提高代码运行效率。
复制代码 代码如下:

Response.Write("" & _
"" & _
"Response Test" & _
"" & _
"" & _
"

Response Test

" & _
"
First Name:" & FirstName & "
Middle Initial:" & MiddleInitial & "
First Name:" & FirstName & "
" & _
"" & _
...
"" & _
"
First Name:" & FirstName & "
Birth Date:" & BirthDate & "
" & _
"" & _
"")

/app1/response3.asp片断

最好记录 = 8.08 毫秒/页
响应时间 = 7.05 毫秒/页
差  额 = -1.03 毫秒 (减少 12.7%)




   这是目前为止最好的方法。

   2.5 合并多个Response.Write,且在每一行的末尾增加CRLF

   也有人非常关注他们的HTML代码在浏览器端是否美观,因此我们又在每一行HTML代码的末尾加上了一个回车,使用的是vbCRLF常量,其他的测试代码与上例一样。
...
Response.Write("" & vbCRLF & _
"" & vbCRLF & _
" Response Test" & vbCRLF & _
"" & vbCRLF & _
...
/app1/response5.asp片断

最好记录 = 7.05 毫秒/页
响应时间 = 7.63 毫秒/页
差  额 = +0.58 毫秒 (增加 8.5%)




   结果是性能略有下降,这可能是因为增加了字符串连接操作,同时输出的文本也增加了。

   2.6 意见

   根据上述ASP输出测试的结果,我们得出如下编码规则:

避免过多地使用内嵌ASP。
把尽可能多的Response.Write语句合并成单个语句。
绝对不要为了加上CRLF而封装Response.Write。
如果要格式化HTML输出,直接在Response.Write语句后面加上CRLF。

纲要:ASP动态生成的内容以什么方式输出效率最高?最好用哪种方法提取数据库记录集?本文测试了近20个这类ASP开发中常见的问题,测试工具所显示的时间告诉我们:这些通常可以想当然的问题不仅值得关注,而且还有出乎意料的秘密隐藏在内。

一、测试目的

   本文的第一部分考察了ASP开发中的一些基本问题,给出了一些性能测试结果以帮助读者理解放入页面的代码到底对性能有什么影响。ADO是由Microsoft开发的一个通用、易用的数据库接口,事实证明通过ADO与数据库交互是ASP最重要的应用之一,在第二部分中,我们就来研究这个问题。

   ADO所提供的功能相当广泛,因此准备本文最大的困难在于如何界定问题的范围。考虑到提取大量的数据可能显著地增加Web服务器的负载,所以我们决定这一部分的主要目的是找出什么才是操作ADO记录集的最优配置。然而,即使缩小了问题的范围,我们仍旧面临很大的困难,因为ADO可以有许多种不同的方法来完成同一个任务。例如,记录集不仅可以通过Recordset类提取,而且也可以通过Connection和Command类提取;即使得到记录集对象之后,还有许多可能戏剧性地影响性能的操作方法。然而,与第一部分一样,我们将尽可能地涵盖最广泛的问题。

   具体地讲,这一部分的目标是收集足够多的信息,回答下列问题:

l是否应该通过包含引用ADOVBS.inc?
l使用记录集时是否应该创建单独的连接对象?
l最好用哪种方法提取记录集?
l哪种游标类型和记录锁定方式效率最高?
l是否应该使用本地记录集?
l设置记录集属性用哪种方法最好?
l用哪种方法引用记录集字段值效率最高?
l用临时字符串收集输出是一种好方法吗?

二、测试环境

   本测试总共用到了21个ASP文件,这些文件可以从本文后面下载。每一个页面设置成可以运行三种不同的查询,分别返回0、25、250个记录。这将帮助我们隔离页面本身的初始化、运行开销与用循环访问记录集的开销。

   为便于测试,数据库连接字符串和SQL命令串都在Global.asa中作为Application变量保存。由于我们的测试数据库是SQL Server 7.0,因此连接串指定OLEDB作为连接提供者,测试数据来自SQL Server的Northwind数据库。SQL SELECT命令从NorthWind Orders表提取7个指定的字段。
复制代码 代码如下:



'alternate sql - 25 records
Application("SQL") = "SELECTTOP 25OrderID, " & _
"CustomerID, " & _
"EmployeeID, " & _
"OrderDate, " & _
"RequiredDate, " & _
"ShippedDate, " & _
"Freight " & _
"FROM[Orders] "

'alternate sql - 250 records
Application("SQL") = "SELECTTOP 250 OrderID, " & _
"CustomerID, " & _
"EmployeeID, " & _
"OrderDate, " & _
"RequiredDate, " & _
"ShippedDate, " & _
"Freight " & _
"FROM[Orders] "

   测试服务器配置如下:450 Mhz Pentium,512 MB RAM,NT Server 4.0 SP5,MDAC 2.1(数据访问组件),以及5.0版本的Microsoft脚本引擎。SQL Server运行在另外一台具有类似配置的机器上。和第一部分一样,我们仍旧使用Microsoft Web Application Stress Tool 记录从第一个页面请求到从服务器接收到最后一个字节的时间(TTLB,Time To Last Byte),时间以毫秒为单位。测试脚本调用每个页面1300次以上,运行时间约20小时,以下显示的时间是会话的平均TTLB。请记住,和第一部分一样,我们只关心代码的效率,而不是它的可伸缩性或服务器性能。

   同时请注意我们启用了服务器的缓冲。另外,为了让所有的文件名字长度相同,有的文件名字中嵌入了一个或多个下划线。
三、第一次测试

   在第一次测试中,我们模拟Microsoft ASP ADO示例中可找到的典型情形提取一个记录集。在这个例子(ADO__01.asp)中,我们首先打开一个连接,然后创建记录集对象。当然,这里的脚本按照本文第一部分所总结的编码规则作了优化。
复制代码 代码如下:

<% Option Explicit %>

<%
Dim objConn
Dim objRS

Response.Write( _
"" & _
"ADO Test" & _
"" _
)

Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open Application("Conn")

Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.ActiveConnection = objConn
objRS.CursorType = adOpenForwardOnly
objRS.LockType = adLockReadOnly
objRS.Open Application("SQL")

If objRS.EOF Then
Response.Write("No Records Found")
Else
'write headings
Response.Write( _
"" & _
"" & _
"" & _
"" & _
"" & _
"" & _
"" & _
"" & _
"" & _
"" _
)
'write data
Do While Not objRS.EOF
Response.Write( _
"" & _
"" & _
"" & _
"" & _
"" & _
"" & _
"" & _
"" & _
" " _
)
objRS.MoveNext
Loop
Response.Write("
OrderIDCustomerIDEmployeeIDOrderDateRequiredDateShippedDateFreight
" & objRS("OrderID") & "" & objRS("CustomerID") & "" & objRS("EmployeeID") & "" & objRS("OrderDate") & "" & objRS("RequiredDate") & "" & objRS("ShippedDate") & "" & objRS("Freight") & "
")
End If

objRS.Close
objConn.Close
Set objRS = Nothing
Set objConn = Nothing

Response.Write("")
%>

   下面是测试结果:

   我们来看一下各栏数字的含义:
0返回0个记录的页面所需要的TTLB(毫秒)。在所有的测试中,该值被视为生成页面本身(包括创建对象)的时间开销,不包含循环访问记录集数据的时间。
25以毫秒计的提取和显示25个记录的TTLB
tot time/25"25"栏的TTLB除以25,它是每个记录的总计平均时间开销。
disp time/25"25"栏的TTLB减去"0"栏的TTLB,然后除以25。该值反映了在循环记录集时显示单个记录所需时间。
250提取和显示250个记录的TTLB。
tot time/250"250"栏的TTLB除以25,该值代表单个记录的总计平均时间开销。
disp time/250"250"栏的TTLB减去"0"栏的TTLB,再除以250。该值反映了在循环记录集时显示单个记录所需时间。

   上面的测试结果将用来同下一个测试结果比较。
四、是否应该通过包含引用ADOVBS.inc?

   Microsoft提供的ADOVBS.inc包含了270行代码,这些代码定义了大多数的ADO属性常量。我们这个示例只从ADOVBS.inc引用了2个常量。因此本次测试(ADO__02.asp)中我们删除了包含文件引用,设置属性时

-六神源码网