程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> ASP編程 >> ASP技巧 >> 如何增強ASP程序性能(1)

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

編輯:ASP技巧

簡介

  性能是一個很重要的特征。你需要事先設計好性能指標,否則日後就要為此重新編寫程序。就是說:要設想好怎樣最佳化地執行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 = "<select name=""EmploymentStatus">" & vbCrLf
Set fldName = rs.Fields("StatusName") ' ADO FIEld Binding
Do Until rs.EOF
' Next line violates Don't Do String Concats,
' but it's OK because we are building a cache
s = s & " <option>" & fldName & "</option>" & vbCrLf
rs.MoveNext
Loop
s = s & "</select>" & 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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved