![]() |
|
如何增强ASP程序性能
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
广告招租,e-mail:yesize@hotmail.com
$#@60;%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 = dEnd Function%$#@62; 对于不同的数据,可以编写类似的函数代码。数据应该按什么格式保存?任何变量类型都可以,因为所有的脚本变量都是不同的。比如说,可以保存为字符串、整型或者数据。通常,将ADO记录集的内容存储到这些变量类型中一个。为了从ADO记录集中取出数据,需要手工地拷贝数据到VBScript变量中,每次一个字段。使用任意一个ADO记录集的函数functions GetRows(),GetString() 或者 Save() (ADO 2.5)都非常得快速而且简单,这里有个函数,描述了如何使用GetRows()返回记录集数据的数组: Get Recordset, return as an ArrayFunction 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 = NothingEnd Function上述代码的一个更深的技巧是为列表缓存了HTML。下面是个简单的例子: Get Recordset, return as HTML Option listFunction FetchEmploymentStatusList Dim rs, fldName, s Set rs = CreateObject(ADODB.Recordset) rs.Open select StatusName, StatusID from EmployeeStatus, _ dsn=employees;uid=sa;pwd=; s = $#@60;select name=EmploymentStatus$#@62; & vbCrLf Set fldName = rs.Fields(StatusName) ADO Field Binding Do Until rs.EOF Next line violates Dont Do String Concats, but its OK because we are building a cache s = s & $#@60;option$#@62; & fldName & $#@60;/option$#@62; & vbCrLf rs.MoveNext Loop s = s & $#@60;/select$#@62; & vbCrLf rs.Close Set rs = Nothing See Release Early FetchEmploymentStatusList = s Return data as a StringEnd Function在合适的环境下,可以在Application或者Session中缓存ADO记录集本身,但是有2点提示:
当在Application或Session中保存数据后,数据将一直保持,除非程序改变它、Session变量到期或者Web应用程序重新启动。如果数据需要更新,怎么办?可以调用只有管理员才能访问的ASP页面来更新数据,或者,通过函数周期性的自动更新数据。下面的例子中,与缓存数据一起保存了时钟标记,过一段时间后,就刷新数据。 $#@60;% error handing not shown...Const UPDATE_INTERVAL = 300 Refresh interval, in seconds Function to return the employment status listFunction GetEmploymentStatusList UpdateEmploymentStatus GetEmploymentStatusList = Application(EmploymentStatusList)End Function Periodically update the cached dataSub UpdateEmploymentStatusList Dim d, strLastUpdate strLastUpdate = Application(LastUpdate) If (strLastUpdate = ) Or _ (UPDATE_INTERVAL $#@60; 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 IfEnd 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()函数负责保存和调入磁盘上的记录集。另外还有一些组件:
技巧4:避免在Application或Session对象中缓存非轻快型组件 在Application或Session对象中缓存数据是一个很好的方法,但是,缓存COM对象却有严重的缺陷。在Application或Session对象中缓存经常使用的COM对象这个工作是非常吸引人的,但是很不幸,许多COM对象,包括用Visual Basic 6.0或者以前版本编写的对象组件,当存储在Application或Session对象中后,都会产生严重的瓶颈问题。 特别地,当组件编写得不是很轻巧时,就极可能产生瓶颈问题。一个轻型组件就是标记了ThreadingModel=Both的组件,其中合计了自由线程的排列(FTM),或者标记了ThreadingModel=Neutral(Neutral模式是Windows2000和COM+中的新特征)。下面的组件不是轻型的:
如果缓存了非轻型组件,将会发生什么错误?在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。
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||