简介
性能是一个特性您需要预先设计性能或是在日后重新编写应用程序换句话说什么是最大限度优化 Active Server Pages (ASP) 应用程序性能的好策略?
本文为优化 ASP 应用程序和Visual Basic(R) 脚本编辑器 (VBScript)提供了许多技巧对许多陷阱和缺陷进行了讨论本文所列的建议均在 及其他站点上进行了测试而且工作正常本文假定您对 ASP 开发有基本的理解包括对 VBScript 和/或 JScriptASP ApplicationASP Session 和其他 ASP 内部对象(请求响应和服务器)
ASP 的性能通常不止取决于 ASP 代码本身我们并不想在一篇文章中囊括所有的至理名言只在最后列出与性能相关的资源这些链接包括 ASP 和非 ASP 主题包括ActiveX(R) 数据对象 (ADO)部件对象模型 (COM)数据库和Internet 信息服务器 (IIS)配置这些是我们喜欢的链接 务请关注它们
技巧 在 Web 服务器上缓存常用数据
典型的 ASP 页从后端数据库检索数据然后将结果转换为超文本标记语言 (HTML)无论数据库的速度如何从内存检索数据要比从后端数据库检索数据快得多从本地硬盘读取数据通常也要比从数据库检索数据快得多因此通常可以通过在 Web 服务器(在内存或磁盘)上缓存数据来改善性能
缓存是典型的空间与时间的折衷如果恰当地缓存数据您将看到性能会有惊人的提高为使缓存发挥效力它必须保持经常重用的数据而且重新计算这些数据的代价是昂贵的或比较昂贵的如果缓存充满了垃圾数据则是对存储器的浪费
不经常变化的数据也是缓存的候选数据因为您无须担心数据与数据库的同步问题组合框引用表DHTML 碎片可扩展标记语言 (XML) 字符串菜单项和站点配置变量(包括数据源名称 (DSN)Internet 协议 (IP) 地址和 Web 路径)都是缓存的候选数据注意您可以缓存数据的表示而不是数据本身如果 ASP 页不经常更改而且缓存的成本也非常高(例如整个产品目录)请考虑预先生成 HTML而不是在每次请求时重新绘制
数据应缓存在何处有哪些缓存策略?数据经常缓存在 Web 服务器内存或 Web 服务器磁盘上下面两个技巧讨论这些选项
技巧 在 Application 或 Session 对象中缓存常用数据
ASP Application 和 Session 对象为在内存中缓存数据提供了方便的容器既可以将数据赋予 Application 对象也可将数据赋予 Session 对象这些数据在 HTTP 调用中将保留在内存中Session 数据按用户存储而 Application 数据在所有用户间共享
何时将数据载入 Application 或 Session?通常在 Application 或 Session 启动时加载数据要在 Application 或 Session 启动时加载数据请在下面两函数中添加相应的代码
Application_OnStart()
或
Session_OnStart()
这两个函数应该位于 Globalasa如果没有可以添加这些函数也可以在第一次需要数据时加载数据要进行上述操作请在 ASP 页中添加一些代码(或编写可重用的脚本函数)这些代码检查数据是否存在并在数据不存在时加载数据这是称为迟缓计算的经典性能技术的例子 在您的确需要它之前不进行计算请看例子
<%
Function GetEmploymentStatusList
Dim d
d = Application(EmploymentStatusList)
If d = Then
FetchEmploymentStatusList 函数(不显示)
从 DB 中取出数据返回数组
d = FetchEmploymentStatusList()
Application(EmploymentStatusList) = d
End If
GetEmploymentStatusList = d
End Function
%>
可以为每一块所需的数据编写类似的函数
数据应该以什么格式存储?任何变量类型均可存储因为所有脚本变量是各不相同的例如可以存储字符串整型或数组通常您将以这些变量类型之一存储 ADO 记录集的内容若要获取 ADO 记录集衍生的数据可以手工将数据复制到 VBScript 变量中每次一个字段使用一个 ADO 记录集保留函数 GetRows()GetString() 或 Save() (ADO )会更快更简便完整而详细的内容已超出了本文的范围下面的演示函数使用了
GetRows()
来返回记录集数据的数组
取记录集以数组返回
Function FetchEmploymentStatusList
Dim rs
Set rs = createObject(ADODBRecordset)
rsOpen select StatusName StatusID from EmployeeStatus _
dsn=employees;uid=sa;pwd=;
FetchEmploymentStatusList = rsGetRows() 以数组返回数据
rsClose
Set rs = Nothing
End Function
对上面示例的进一步改进应当是缓存该列表的 HTML而不是缓存数组下面是一个简单的范例
取记录集以HTML 选项列表返回
Function FetchEmploymentStatusList
Dim rs fldName s
Set rs = createObject(ADODBRecordset)
rsOpen select StatusName StatusID from EmployeeStatus _
dsn=employees;uid=sa;pwd=;
s = <select name=EmploymentStatus> & vbCrLf
Set fldName = rsFields(StatusName) ADO 字段绑定
Do Until rsEOF
下面一行违背了不要进行字符串连接
但这是可以的因为我们正在建立高速缓存
s = s & <option> & fldName & </option> & vbCrLf
rsMoveNext
Loop
s = s & </select> & vbCrLf
rsClose
Set rs = Nothing 参见尽早释放
FetchEmploymentStatusList = s 以字符串返回数据
End Function
在正常的情况下可以在 Application 或 Session 作用域中缓存 ADO 记录集本身有两个警告
ADO 必须为标记的自由线程
必须使用断开连接的记录集
如果不能保证满足这两个要求请不要缓存 ADO 记录集在下面的非灵活组件和不要缓存连接技巧中我们将讨论在 Application 或 Session 作用域中存储 COM 对象的危险
如果在 Application 或 Session 作用域中存储数据这些数据将一直保留在那儿直到在程序中改变它Session 过期或 Web 应用程序重新启动时为止数据需要更新如何处理?若要用手工强制更新应用程序数据可以调用只允许管理员访问的数据更新 ASP 页另外还可以通过函数周期地自动刷新数据下面的示例存储带缓存数据的时间戳在指定时间间隔后刷新数据
<%
未显示错误处理
Const update_INTERVAL = 刷新时间间隔以秒计
函数返回雇佣状态列表
Function GetEmploymentStatusList
updateEmploymentStatus
GetEmploymentStatusList = Application(EmploymentStatusList)
End Function
定期更新缓存的数据
Sub updateEmploymentStatusList
Dim d strLastupdate
strLastupdate = Application(Lastupdate)
If (strLastupdate = ) Or _
(update_INTERVAL DateDiff(s strLastupdate Now)) Then
注意此处可能有两个或多个调用这是可以的只不过
产生几个不必要的取指令罢了(就此有一个工作区)
FetchEmploymentStatusList 函数(不显示)
从 DB 中取数据返回一个数组
d = FetchEmploymentStatusList()
更新 Application 对象用 ApplicationLock()
来确保一致的数据
ApplicationLock
Application(EmploymentStatusList) = d
Application(Lastupdate) = CStr(Now)
ApplicationUnlock
End If
End Sub
其他示例请参阅具有 Application 数据的最快列表框(英文)
请注意在 Session 或 Application 对象中缓存大型数组并非上策在访问数组元素之前脚本语言的语法要求建立整个数组的临时副本例如如果在 Application 对象中缓存了将美国邮政编码映射到本地气象站的字符串数组该字符串数组有 个元素ASP 在找出一个字符串之前必须将所有 个气象站复制到临时数组中在这种情况下建立带自定义方法的自定义组件来存储气象站 或使用一个字典组件也许更好
请不要在倒洗澡水时把孩子一同倒掉对这种观点的一个新的注解是数组提供了对内存中相邻关键数据对的快速查找和存储索引字典比索引数组要慢您应该根据具体情况选择能够提供最佳性能的数据结构
技巧 在 Web 服务器磁盘上缓存数据和 HTML
有时数据过多不能在内存中进行缓存过多是一种定性的判断它取决于打算消耗的内存量还有缓存项的数量和这些项的检索频率总之如果有过多的数据要在内存中缓存请考虑以文本或 XML 文件的形式在 Web 服务器的硬盘上缓存数据可以将在磁盘上缓存数据和在内存中缓存数据组合起来为站点建立最优的缓存策略
注意在度量单个 ASP 页的性能时在磁盘上检索数据不一定比从数据库中检索数据快但是缓存减轻了数据库和网络的负荷在高负荷情况下这将明显提高总体通信量在查询成本很高时缓存查询的结果缓存便非常有效例如多表联合或复杂的存储过程或缓存大型的结果集按照