您的位置:首页技术开发ASP技巧 → 如何增强ASP程序性能1

如何增强ASP程序性能1

时间:2004/11/7 4:03:00来源:本站整理作者:蓝点我要评论(0)

 



                 如何增强ASP程序性能(1)

               2000-08-10· 甘冀平·Yesky



简介



  性能是一个很重要的特征。你需要事先设计好性能指标,否则日后就要为此重新编写程序。就是说:要设想好怎样最佳化地执行ASP程序?



  本文提出了一些优化ASP应用和VBScript的技巧,许多技巧和缺陷都经过了研讨。这里列出的建议已经在http://www.microsoft.com 和其他站点上进行了测试,都工作得非常好。本文假设你具备ASP开发的基本知识,包括VBScript或者JScript,ASP应用程序,ASP Session,以及其他ASP内置对象(Request,Response和Server)。



  通常,ASP的执行性能远远不仅仅依赖ASP代码本身!在本文的尾部列出了与性能相关的资源,它们含概了ASP和非ASP的部分,包含ActiveX Data Objects(ADO),Component Object Model(COM),数据库(Database),以及Internet信息服务器(IIS)的配置。除了这些,还有一些非常好的链接值得你一看。



技巧1:在Web服务器上缓存经常使用的数据



  典型的情况是:ASP页面从后台存储中取回数据,然后以超文本标记语言(HTML)的形式形成结果。不管数据库的速度如何,从内存中取回数据要比从后台存储设备中快得多。从本地硬盘读取数据通常也非常快。所以,提高性能可以通过缓存服务器上的数据来实现,无论是将数据缓存在内存中,或者本地硬盘中。



  缓存是经典的“空间换时间”的折中方式。如果缓存得恰当,就可以看到显著的性能提升。为了让缓存有效,必须保证缓存数据是经常要重用的,而且也是计算起来繁琐的。装满陈旧数据的缓存是对内存的浪费。



  不经常改变的数据是缓存的较好对象,因为不需要随时考虑这些数据更新后的同步操作。组合框、参考表格、DHTML代码、扩展标记语言串、菜单以及站点配置变量(包括数据源名字DSNS,Internet协议地址IP以及Web路径)都是很好的缓存对象。注意:要缓存数据表达式而不是数据本身。如果一个ASP页面经常变化并且很费力去缓存(比如整个产品目录),就要考虑预产生HTML,而不是每次发生请求时再描述它。



技巧2:在Application或Session对象中缓存经常使用的数据



  ASP中的Application和Session对象是在内存中缓存数据的便利容器。你可以将数据赋值给Application和Session对象,这些数据在HTTP调用期间将一直保持在内存中。Session中的数据是为每一个用户服务的,Application中的数据是所有用户共享的。



  何时需要在Application和Session中装入数据?通常,当应用程序启动或者会话开始时,数据就被装入了。为了在这时装入数据,在Application OnStart()或者Session OnStart()中分别添加适当的代码。这些函数位于文件Global.asa中,如果原来不存在,就添加上。也可以在数据首次需要的时候调入,在ASP页面中添加代码,检查数据是否存在,如果没有发现,就调入它。这里有一个例子,它代表了被称为“lazy evalution”的经典性能处理技术:直到需要时,再去计算。例子如下:



<%

Function GetEmploymentStatusList

Dim d

d = Application("EmploymentStatusList")

If d = "" Then

' FetchEmploymentStatusList function (not shown)

' fetches data from DB, returns an Array

d = FetchEmploymentStatusList()

Application("EmploymentStatusList") = d

End If

GetEmploymentStatusList = d

End Function

%>



对于不同的数据,可以编写类似的函数代码。



  数据应该按什么格式保存?任何变量类型都可以,因为所有的脚本变量都是不同的。比如说,可以保存为字符串、整型或者数据。通常,将ADO记录集的内容存储到这些变量类型中一个。为了从ADO记录集中取出数据,需要手工地拷贝数据到VBScript变量中,每次一个字段。使用任意一个ADO记录集的函数functions GetRows(),GetString() 或者 Save() (ADO 2.5)都非常得快速而且简单,这里有个函数,描述了如何使用GetRows()返回记录集数据的数组:



' Get Recordset, return as an Array

Function FetchEmploymentStatusList

Dim rs

Set rs = CreateObject("ADODB.Recordset")

rs.Open "select StatusName, StatusID from EmployeeStatus", _

"dsn=employees;uid=sa;pwd=;"

FetchEmploymentStatusList = rs.GetRows() " Return data as an Array

rs.Close

Set rs = Nothing

End Function



上述代码的一个更深的技巧是为列表缓存了HTML。下面是个简单的例子:



' Get Recordset, return as HTML Option list

Function FetchEmploymentStatusList

Dim rs, fldName, s

Set rs = CreateObject("ADODB.Recordset")

rs.Open "select StatusName, StatusID from EmployeeStatus", _

"dsn=employees;uid=sa;pwd=;"

s = "" & vbCrLf

rs.Close

Set rs = Nothing ' See Release Early

FetchEmploymentStatusList = s ' Return data as a String

End Function



在合适的环境下,可以在Application或者Session中缓存ADO记录集本身,但是有2点提示:



ADO必须是自由线程标记的

需要使用disconnected recordset方式

  如果不能保证上述2个条件,就不要缓存ADO记录集,因为这会产生很大的危险性。



  当在Application或Session中保存数据后,数据将一直保持,除非程序改变它、Session变量到期或者Web应用程序重新启动。如果数据需要更新,怎么办?可以调用只有管理员才能访问的ASP页面来更新数据,或者,通过函数周期性的自动更新数据。下面的例子中,与缓存数据一起保存了时钟标记,过一段时间后,就刷新数据。



<%

' error handing not shown...

Const UPDATE_INTERVAL = 300 ' Refresh interval, in seconds



' Function to return the employment status list

Function GetEmploymentStatusList

UpdateEmploymentStatus

GetEmploymentStatusList = Application("EmploymentStatusList")

End Function



' Periodically update the cached data

Sub UpdateEmploymentStatusList

Dim d, strLastUpdate

strLastUpdate = Application("LastUpdate")

If (strLastUpdate = "") Or _

(UPDATE_INTERVAL < DateDiff("s", strLastUpdate, Now)) Then



' Note: two or more calls might get in here. This is okay and will simply

' result in a few unnecessary fetches (there is a workaround for this)



' FetchEmploymentStatusList function (not shown)

' fetches data from DB, returns an Array

d = FetchEmploymentStatusList()



' Update the Application object. Use Application.Lock()

' to ensure consistent data

Application.Lock

Application("EmploymentStatusList") = d

Application("LastUpdate") = CStr(Now)

Application.Unlock

End If

End Sub



有另外一个例子,请参阅 World’s Fastest ListBox with Application Data。



  必须意识到,在Session或者Application对象中缓存大容量的数组不是一个好的方法。存取数组中任何元素前,脚本语言的规则要求首先要建立整个数组的临时备份。比如,如果在Application对象中缓存一个100,000个元素的数组,其中包含U.S.邮政编码与本地气象站的对应关系,ASP就必须首先拷贝所有100,000个气象站信息到临时数组中,然后才能选择其中一个字符串进行处理。在这种情况下,创建一个定制的组件,编写一个方法存储气象站信息,是非常好的方法。



技巧3:在Web服务器磁盘上缓存数据和HTML页面



  有时候,有“许多”数据要在内存中缓存。“许多”是相对而言的,它取决于能消耗多少内存、缓存项目的数量以及取回数据的频度。任何情况下,如果需要在内存中缓存大量的数据,请考虑以text或者XML文件格式在Web服务器硬盘上做缓存。当然,也可以混合使用硬盘缓存数据以及内存缓存数据,从而达到最佳缓存。



  注意:当测试一个单一ASP页面的性能时,从磁盘取回数据不一定比从网络数据库中取回数据快,但是缓存减少了网络数据库的调用。在大规模调用时,这将明显地提高网络的吞吐能力。缓存一个费时的查询结果是非常有用的,比如对于一个复杂的存储过程,或者大量的结果数据。



  ASP和COM提供了几种建立基于磁盘缓冲配置的工具。ADO记录集的Save()和 Open()函数负责保存和调入磁盘上的记录集。另外还有一些组件



Scripting.FileSystemObject 允许你创建、读取和写文件

MSXML,Microsoft XML 解析器随Internet Explorer而来,支持保存和装入XML文档

LookupTable对象(比如在MSN上使用)是从磁盘调入简单列表的很好选择。

  最后,考虑缓存磁盘数据的表达式,而不是数据本身。预处理的HTML可以存储为.htm或者.asp文件,链接直接指向它们。使用诸如XBuilder或者Microsoft SQL Server Internet发布类的商业工具,能够自动处理这些过程。而且,也可以在.asp文件中包含HTML程序片断。同样,也可使用FileSystemObject从磁盘上读取HTML文件,或者使用XML for early rendering来做这个工作。



技巧4:避免在Application或Session对象中缓存非轻快型组件



  在Application或Session对象中缓存数据是一个很好的方法,但是,缓存COM对象却有严重的缺陷。在Application或Session对象中缓存经常使用的COM对象这个工作是非常吸引人的,但是很不幸,许多COM对象,包括用Visual Basic 6.0或者以前版本编写的对象组件,当存储在Application或Session对象中后,都会产生严重的瓶颈问题。



  特别地,当组件编写得不是很轻巧时,就极可能产生瓶颈问题。一个轻型组件就是标记了ThreadingModel=Both的组件,其中合计了自由线程的排列(FTM),或者标记了ThreadingModel=Neutral(Neutral模式是Windows2000和COM+中的新特征)。下面的组件不是轻型的:



Free-threaded组件(除非被集合成FTM)

Apartment-threaded组件

Single-threaded组件

  Configured components不是轻型组件,除非它们是Neutral-threaded的。Apartment-threaded组件和其他非轻型组件在页范围内工作得很好,就是说,它们是在一个单一ASP页面中创建并释放的。



  如果缓存了非轻型组件,将会发生什么错误?在Session对象中缓存的非轻型组件将会“锁住”会话。ASP维护着一个响应请求的工作线程池,通常,新的请求被第一个可用的工作线程控制。如果一个会话被锁在一个线程中,那么请求就被迫等待到相关的线程变为可用。这里有一个类比:你前往一个超级市场,挑选了一些食品,并在3号付款台付款。从那以后,只要在那个超级市场买食品付款,你就会经常到3号付款台去,虽然其他的付款台人少些甚至没有人。



技巧5:不要在Application或Session对象中缓存数据库连接



  缓存ADO连接通常不是一个好的策略。如果一个连接对象被存储在Application对象中,并在所有的页面使用,那么所有页面将会争夺该连接的使用。如果存储在ASP Session对象中,那么将要为每一个用户都打开数据库连接。这将挫败连接池的使用意图,并且在Web服务器数据库上都施加了不必要的高代价压力。



  为了替代缓存数据库连接,可以在使用ADO的每个ASP页面中创建并释放ADO对象。这将非常有效,因为IIS拥有内建的数据库连接池。更准确地说,IIS自动处理OLEDB和ODBC连接池,这将保证在每个页面创建并且释放连接的工作高效进行。



  由于连接的记录集存储了数据库连接的参考,所以,不要在Application或Session对象中缓存连接的记录集。然而,可以安全地缓存disconnected类型的记录集,它们并不保存相应数据库连接的参考。为了断开记录集,执行下面2步:



Set rs = Server.CreateObject("ADODB.RecordSet")

rs.CursorLocation = adUseClient ' step 1



' Populate the recordset with data

rs.Open strQuery, strProv



' Now disconnect the recordset from the data provider and data source

rs.ActiveConnection = Nothing ' step 2



  更多的关于连接池的信息请访问 ADO and SQL Server。






相关阅读 Windows错误代码大全 Windows错误代码查询激活windows有什么用Mac QQ和Windows QQ聊天记录怎么合并 Mac QQ和Windows QQ聊天记录Windows 10自动更新怎么关闭 如何关闭Windows 10自动更新windows 10 rs4快速预览版17017下载错误问题Win10秋季创意者更新16291更新了什么 win10 16291更新内容windows10秋季创意者更新时间 windows10秋季创意者更新内容kb3150513补丁更新了什么 Windows 10补丁kb3150513是什么

文章评论
发表评论

热门文章 没有查询到任何记录。

最新文章 VB.NET 2005编写定时关 Jquery get/post下乱码解决方法 前台gbk gb如何使用数据绑定控件显示数据ASP脚本循环语句ASP怎么提速

人气排行 轻松解决"Server Application Error"和iis"一起学习DataGridView调整列宽用ASP随机生成文件名的函数Jquery get/post下乱码解决方法 前台gbk gbODBC Drivers错误80004005的解决办法返回UPDATE SQL语句所影响的行数的方法用Javascript隐藏超级链接的真实地址两个不同数据库表的分页显示解决方案