台灣最大程式設計社群網站
線上人數
693
 
會員總數:244988
討論主題:188956
歡迎您免費加入會員
討論區列表 >> 專欄文章 >> 改善ASP效能的訣竅-2 (Nancy Cluts 著)
[]  
[我要回覆]
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
改善ASP效能的訣竅-2 (Nancy Cluts 著)
價值 : 0 QP  點閱數:2905 回應數:0

樓主

站務人員 站長
門外漢
0 1580
542 9
發送站內信

捐贈 VP 給 站務人員
訣竅 2: 將經常使用的資料快取在應用程式或工作階段物件中
ASP 應用程式和工作階段物件提供將資料快取在記憶體中的簡便容器。您可以將資料指派到應用程式和工作階段物件中,這些資料在 HTTP 呼叫之間將會存留在記憶體中。工作階段資料是按使用者存放的,而應用程式資料在所有使用者之間共用。

什麼時候將資料載入到應用程式或工作階段中呢?通常,資料是在啟動應用程式或工作階段時載入。要在應用程式或工作階段啟動程序中載入資料,應將適當的程式碼分別新增到 Application_OnStart() 或 Session_OnStart() 中。這些函數應位於 Global.asa 中,如果沒有,可以新增這些函數。您也可以在第一次有需要時載入該資料。要進行這項工作,在 ASP 畫面中新增一些程式碼 (或編寫一個可重複使用的 script 函數),以檢查資料是否存在,如果不存在,就載入資料。這是一個傳統的效能技術,稱為「惰性評估」 - 在您知道需要某一個東西之前不加以計算。例如:

<%
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
%>


您可以為所需的每個資料塊編寫類似的函數。

應該以什麼格式存放資料?可以存放任何形態,因為所有 script 變數都是變體。例如,您可以存放字串、整數或陣列。通常,您將以這些變體類型之一存放 ADO 記錄集的內容。要從 ADO 記錄集獲取資料,您可以手動將資料複製到 VBScript 變數,一次一個欄位。使用其中一個 ADO 記錄集持續函數 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


「在適當的條件下」,可以將 ADO 記錄集本身快取在應用程式或工作階段領域中。有兩點要注意的:

必須將 ADO 標記為無限制執行緒
必須使用中斷連線的記錄集。
如果不能保證滿足這兩個需求,則不要快取 ADO 記錄集。在下面的「非敏捷元件」和「不要快取連線」訣竅中,我們將討論將 COM 物件存放在應用程式或工作階段領域中的危險性。

當您將資料存放在應用程式或工作階段領域時,資料將存留在那堙A直到您以程式改變它、工作階段過期,或 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?) = Events
Application(?LastUpdate?) = CStr(Now)
Application.Unlock
End If
End Sub


請參閱 World's Fastest ListBox with Application Data 中的另一個範例。

請注意在工作階段或應用程式物件中快取大型陣列的做法不是很好。在存取陣列的任何元件之前,script 語言的語義要求必須暫時複製整個陣列。例如,如果將由字串組成的有 100,000 個元件的陣列 (該陣列將美國郵遞區號對應到當地的氣象站) 快取在應用程式物件中,ASP 必須先將所有的 100,000 個氣象站複製到暫時陣列中,然後才能提取一個字串。在這種情況下,用自訂方法建立一個自訂元件來存放區氣象站 - 或使用字典元件會更好。

另一個建議是,不要將嬰兒與洗澡水一起倒掉:陣列能快速查尋和存放在記憶體中鄰近的主索引鍵/資料對。索引字典比索引陣列要慢得多。應針對您的實際情況,選擇提供最佳效能的資料結構。

本篇文章發表於2000-09-09 00:00
別忘捐VP感謝幫助你的人 新手會員瞧一瞧
目前尚無任何回覆
   

回覆
如要回應,請先登入.