在适当的条件下,可以将ADO记录集本身缓存在Application或Session作用域中。有两个警告:必须将ADO标记为自由线程必须使用断开连接的记录集。如果不能保证满足这两个要求,则不要缓存ADO记录集。在下面的“非敏捷组件”和“不要缓存连接”技巧中,我们将讨论将COM对象存储在Application或Session作用域中的危险性。当您将数据存储在Application或Session作用域时,数据将保留在那里,直到您以编程方式改变它、Session过期或Web应用程序重新启动为止。如果数据需要更新怎么办?要手工强制对Application数据进行更新,您可以访问只有管理员才可访问的ASP页来更新数据。或者,您可以通过函数定期自动刷新数据。下面例子存储带有缓存数据的时间戳,并隔一段时间后刷新数据。’FunctiontoreturntheemploymentstatuslistFunctionGetEmploymentStatusListUpdateEmploymentStatusGetEmploymentStatusList=Application(?EmploymentStatusList?)EndFunction’PeriodicallyupdatethecacheddataSubUpdateEmploymentStatusListDimd,strLastUpdatestrLastUpdate=Application(?LastUpdate?)If(strLastUpdate=??)Or_(UPDATE_INTERVAL<DateDiff(?s?,strLastUpdate,Now))Then’Note:twoormorecallsmightgetinhere.Thisisokayandwillsimply’resultinafewunnecessaryfetches(thereisaworkaroundforthis)’FetchEmploymentStatusListfunction(notshown)’fetchesdatafromDB,returnsanArrayd=FetchEmploymentStatusList()’UpdatetheApplicationobject.UseApplication.Lock()’toensureconsistentdataApplication.LockApplication(?EmploymentStatusList?)=EventsApplication(?LastUpdate?)=CStr(Now)Application.UnlockEndIfEndSub请参见World’sFastestListBoxwithApplicationData,上面还有一个例子。要知道在Session或Application对象中缓存大的数组不是一个好的做法。在访问数组的任何元素之前,脚本语言的语法要求必须临时复制整个数组。例如,如果将由字符串组成的有100,000个元素的数组(该数组将美国邮政编码映射到当地的气象站)缓存在Application对象中,ASP必须先将所有的100,000个气象站复制到临时数组中,然后才能提取一个字符串。在这种情况下,用自定义方法建立一个自定义组件来存储气象站-或使用一个词典组件会更好。再警告大家一下,不要将婴儿与洗澡水一起倒掉:数组能快速查寻和存储在内存中是邻近的关键数据对。索引一个词典比索引一个数组要慢得多。应针对您的实际情况,选择提供最佳性能的数据结构。
技巧3:将数据和HTML缓存在Web服务器的磁盘上有时,数据可能太多,无法都缓存在内存中。“太多”只是一个说法,这要看您想消耗多少内存,以及需缓存的项目数和检索这些项目的频率。在任何情况下,如果数据太多而无法都缓存在内存中,则考虑将数据以文本或XML文件缓存在Web服务器的硬盘上。可以同时将数据缓存在磁盘和内存中,为您的站点建立最适宜的缓存策略。注意当测量单个ASP页的性能时,检索磁盘上的数据可能不一定要比从数据库检索数据更快。但缓存会降低数据库和网络上的负载。在高负载的情况下,这样做可大大改善总体吞吐量。当缓存开销很大的查询结果(如多表联接或复合存储过程)或大的结果集时,这是非常有效的。与往常一样,要测试一下几种方案的优劣。ASP和COM提供一些建立基于磁盘的缓存方案的工具。ADO记录集
Save()和
Open()函数保存和装载磁盘中的记录集。可以使用这些方法重新编写上面Application数据缓存技巧中的代码示例,用文件的Save()代替写到Application对象中的代码。有一些其它组件可以用于文件:
- Scripting.FileSystemObject可使您创建、读和写文件。
- 与InternetExplorer一起提供的Microsoft®XML解析器(MSXML)支持保存和装载XML文档。
- LookupTable对象(例如,用在MSN上)是从磁盘装载简单列表的最好选择。
- 自由线程的组件(除非它们聚集FTM)。
- 单元线程组件。
- 单线程组件。
- COM对象有利于将表示逻辑与业务逻辑分开。
- COM对象可以保证代码重复使用。
- 许多开发人员发现以VB、C++或VisualJ++编写的代码比ASP更容易调试。
- 低级隔离。这在IIS的所有版本中都得到支持,且是最快的。它在Inetinfo.exe中运行ASP,Inetinfo.exe是主要IIS进程。如果ASP应用程序崩溃,IIS也会崩溃。(要在IIS4.0下重新启动IIS,Web站点管理员应使用诸如InetMon之类的工具监视站点,如果服务器发生故障,应启用批处理文件以重新启动服务器。IIS5.0引入了可靠的重新启动,该方法可使发生故障的服务器自动重新启动。)
- 中级隔离。IIS5.0引入了这个新的级别,它被称为进程外级别,因为ASP在IIS进程之外运行。在中级隔离中,被配置作为中级隔离运行的所有ASP应用程序都共享一个进程空间。这就减少了在一台服务器运行多个进程外ASP应用程序所需要的进程数量。中级隔离是IIS5.0中的默认隔离级别。
- 高级隔离。在IIS4.0和IIS5.0中支持这一级别,高级隔离也是进程外的。如果ASP崩溃,Web服务器并不会崩溃。下次ASP请求时,ASP应用程序就会自动重新启动。在高级隔离中,配置作为高级隔离运行的每个ASP应用程序都在其自有进程空间中运行。这样做可保护ASP应用程序彼此之间不相互干扰。其缺点是它要求每个ASP应用程序都要有一个单独的进程。当在一台服务器上必须运行许多应用程序时,系统开销就会大大增加。
- 在IIS4.0中,使用ASP低隔离级别,使用MTS服务器程序包。
- 在IIS5.0上,使用ASP的中隔离级,并使用COM+库应用程序。技巧10:使用显式选项在.asp文件中应使用OptionExplicit。此指令放在.asp文件的最上面,它强制开发人员声明要使用到的所有变量。许多程序员认为这种方法对于调试应用程序很有帮助,因为这种方法避免了键错变量名和误建新变量的可能性(例如,将MyXMLString=)错写成MyXLMString=...。更重要的一点也许是,声明的变量比未声明的变量速度更快。由此,脚本在运行时每次用到未声明的变量时,按名称引用它。另一方面,声明的变量是有顺序的,要么以编译时间,要么以运行时间。以后,声明的变量都按此顺序引用。因为OptionExplicit强制变量声明,它能确保声明所有变量,因此访问的速度也很快。技巧11:在子例程和函数中使用局部变量局部变量是那些在子例程和函数内声明的变量。在函数或子例程内,局部变量访问比全局变量访问更快。局部变量的使用也会使代码更清晰,因此应尽量使用局部变量。技巧12:将经常使用的数据复制到脚本变量中当访问ASP中的COM对象时,应将经常使用的对象数据复制到脚本变量中。这样做可减少COM方法调用,因为COM方法调用与访问脚本变量相比,开销相对较大。当访问Collection和Dictionary对象时,这种技术也会减少开销很大的查找。一般来说,如果您打算不止一次访问对象数据,那么就应将数据放到脚本变量中。这种优化的主要目标是Request变量(Form和QueryString变量)。例如,您的站点可传递一个名为UserID的QueryString变量。假设此UserID在特定页面上被引用12次。可以无须调用Request(?UserID?)12次,而是在ASP页面最上面将UserID指派到一个变量。然后在该页面自始至终使用该变量。这样就省去了11次COM方法调用。实际上,访问COM属性或方法的开销并没有那么大。下面举一个例子,说明某相当常见的代码(从语法上讲):Foo.bar.blah.baz=Foo.bar.blah.qaz(1)IfFoo.bar.blah.zaq=Foo.bar.blah.abcThen’...