技巧
簡 介 效能是一個特性。您需要預先設計效能,或是在日後重新編寫應用程式。換句話說,什麼是最大限度最佳化 Active Server Pages (ASP) 應用程式效能的好策略?
本文為最佳化 ASP 應用程式和“Visual Basic(R) 指令碼編輯器 (VBScript)”提供了許多技巧。對許多陷阱和缺陷進行了討論。本文所列的建議均在 http://www.microsoft.com 及其他網站上進行了測試,而且工作正常。本文假定您對 ASP 開發有基本的理解,包括對 VBScript 和/或 JScript、ASP Application、ASP Session 和其他 ASP 內部對象(請求、響應和伺服器)。
ASP 的效能,通常不止取決於 ASP 代碼本身。我們並不想在一篇文章中囊括所有的至理名言,只在最後列出與效能相關的資源。這些連結包括 ASP 和非 ASP 主題,包括“ActiveX(R) 資料對象 (ADO)”、“組件物件模型 (COM)”、資料庫和“Internet 資訊服務器 (IIS)”配置。這些是我們喜歡的連結 - 務請關注它們。
技巧 1:在 Web 服務器上緩衝常用資料 典型的 ASP 頁從後端資料庫檢索資料,然後將結果轉換為超文字標記語言 (HTML) (HTML)。無論資料庫的速度如何,從記憶體檢索資料要比從後端資料庫檢索資料快得多。從本地硬碟讀取資料通常也要比從資料庫檢索資料快得多。因此,通常可以通過在 Web 服務器(在記憶體或磁碟)上快取資料來改善效能。
緩衝是典型的空間與時間的折衷。如果恰當地快取資料,您將看到效能會有驚人的提高。為使緩衝發揮效力,它必須保持經常重用的資料,而且重新計算這些資料的代價是昂貴的或比較昂貴的。如果緩衝充滿了垃圾資料,則是對儲存空間的浪費。
不經常變化的資料也是緩衝的候選資料,因為您無須擔心資料與資料庫的同步問題。組合框、參考資料表、DHTML 片段、可延伸標記語言 (XML) (XML) 字串、功能表項目和網站組態變數(包括資料來源名稱 (DSN)、網際網路通訊協定 (IP) (IP) 地址和 Web 路徑)都是緩衝的候選資料。注意,您可以快取資料的表示而不是資料本身。如果 ASP 頁不經常更改,而且緩衝的成本也非常高(例如,整個產品目錄),請考慮預先產生 HTML,而不是在每次請求時重新繪製。
資料應緩衝在何處,有哪些緩衝策略?資料經常緩衝在 Web 服務器記憶體或 Web 服務器磁碟上。下面兩個技巧討論這些選項。
技巧 2:在 Application 或 Session 對象中緩衝常用資料 ASP Application 和 Session 對象為在記憶體中快取資料提供了方便的容器。既可以將資料賦予 Application 對象,也可將資料賦予 Session 對象,這些資料在 HTTP 調用中將保留在記憶體中。Session 資料按使用者儲存,而 Application 資料在所有使用者間共用。
何時將資料載入 Application 或 Session?通常,在 Application 或 Session 啟動時載入資料。要在 Application 或 Session 啟動時載入資料,請在下面兩函數中添加相應的代碼:Application_OnStart() 或 Session_OnStart()。這兩個函數應該位於 Global.asa;如果沒有,可以添加這些函數。也可以在第一次需要資料時載入資料。要進行上述操作,請在 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 2.5),會更快更簡便。完整而詳細的內容已超出了本文的範圍。下面的示範函數使用了 GetRows() 來返回記錄集資料的數組:
' 取記錄集,以數組返回
Function FetchEmploymentStatusList
Dim rs
Set rs = CreateObject("ADODB.Recordset")
rs.Open "select StatusName, StatusID from EmployeeStatus", _
"dsn=employees;uid=sa;pwd=;"
FetchEmploymentStatusList = rs.GetRows() ' 以數組返回資料
rs.Close
Set rs = Nothing
End Function
對上面樣本的進一步改進應當是緩衝該列表的 HTML,而不是緩衝數組。下面是一個簡單的範例:
' 取記錄集,以“HTML 選項”列表返回
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 欄位綁定
Do Until rs.EOF
' 下面一行違背了不要進行字串串連,
' 但這是可以的,因為我們正在建立快取
s = s & " <option>" & fldName & "</option>" & vbCrLf
rs.MoveNext
Loop
s = s & "</select>" & vbCrLf
rs.Close
Set rs = Nothing ' 參見儘早釋放
FetchEmploymentStatusList = s ' 以字串返回資料
End Function
在正常的情況下,可以在 Application 或 Session 範圍中緩衝 ADO 記錄集本身。有兩個警告:
ADO 必須為標記的自由線程
必須使用中斷連線的記錄集。
如果不能保證滿足這兩個要求,請不要緩衝 ADO 記錄集。在下面的非靈活組件和不要緩衝串連技巧中,我們將討論在 Application 或 Session 範圍中儲存 COM 物件的危險。
如果在 Application 或 Session 範圍中儲存資料,這些資料將一直保留在那兒,直到在程式中改變它、Session 到期或 Web 應用程式重新啟動時為止。資料需要更新如何處理?若要用手工強制更新應用程式資料,可以調用只允許管理員訪問的資料更新 ASP 頁。另外,還可以通過函數,周期地自動重新整理資料。下面的樣本儲存帶快取資料的時間戳記,在指定時間間隔後重新整理資料。
<%
' 未顯示錯誤處理...
Const UPDATE_INTERVAL = 300 ' 重新整理時間間隔,以秒計
' 函數返回僱傭狀態列表
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