程式|效能 如何增強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)(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 func