微軟建議的ASP效能最佳化28條規則 之一

來源:互聯網
上載者:User
 效能是一個特徵。您必須預先設計效能,否則您以後就得重寫應用程式。就是說,有哪些好的策略可使 Active Server Pages (ASP) 應用程式效能達到最佳?

  本文介紹了最佳化 ASP 應用程式和 Visual Basic® Scripting Edition (VBScript) 的技巧。本文討論了許多陷阱。本文列出的建議已經在 http://www.microsoft.com 和其它網站中進行了測試,效果十分顯著。本文假定您已經對 ASP 開發,包括 VBScript 和/或 JScript、ASP Application、ASP Session 和其它 ASP 固有對象(Request、Response 和 Server)有了基本瞭解。

  通常,ASP 效能主要取決於 ASP 代碼本身以外的很多因素。我們不在一篇文章中羅列出所有的資訊,在本文結尾處我們列出了與效能有關的資源。這些連結涵蓋了 ASP 和非 ASP 主題,包括 ActiveX® 資料對象 (ADO)、元件物件模型 (COM)、資料庫和 Internet Information Server (IIS) 配置。這些都是我們喜歡的一些連結 - 一定要去看看。

技巧 1:將經常使用的資料緩衝在 Web 服務器上

  典型的 ASP 頁從後端資料存放區中檢索資料,然後將結果轉換成超文字標記語言 (HTML) (HTML)。無論資料庫的速度如何,從記憶體中檢索資料總要比從後端資料存放區中檢索資料快得多。從本地硬碟讀取資料通常也比從資料庫中檢索資料更快。因此,通常可以將資料緩衝在 Web 服務器上(儲存在記憶體或磁碟中),來提高效能。

  緩衝是傳統的以空間換取時間的做法。如果您緩衝的內容正確,那麼您可以看到效能會有顯著的提高。為使緩衝有效,必須儲存那些經常重複使用的資料,且要重新計算這些資料需要(適度)大的開銷。如果緩衝的都是些陳舊的資料,就會造成記憶體浪費。

  不經常發生改變的資料是很好的緩衝候選資料,因為您不必擔心隨著時間的遷移該資料與資料庫同步的問題。組合框列表、參考資料表、DHTML 片段、擴充標記語言 (XML) 字串、功能表項目和網站組態變數(包括資料來源名稱 (DSN)、網際網路通訊協定 (IP) (IP) 地址和 Web 路徑)都是很好的緩衝候選內容。注意您可以快取資料的“表示”,而不快取資料本身。如果 ASP 頁很少更改,且緩衝的開銷也很大(例如,整個產品目錄),則應考慮事先產生 HTML,而不是在響應每個請求時重新顯示。

  應將資料緩衝在哪裡,有哪些緩衝策略?通常,資料緩衝在 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 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 記錄集持久函數 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 記錄集本身緩衝在 Application 或 Session 範圍中。有兩個警告:

  必須將 ADO 標記為自由線程
  必須使用中斷連線的記錄集。
  如果不能保證滿足這兩個要求,則不要緩衝 ADO 記錄集。在下面的“非敏捷組件”和“不要緩衝串連”技巧中,我們將討論將 COM 物件儲存在 Application 或 Session 範圍中的危險性。

  當您將資料存放區在 Application 或 Session 範圍時,資料將保留在那裡,直到您以編程方式改變它、Session 到期或 Web 應用程式重新啟動為止。如果資料需要更新怎麼辦?要手工強制對 Application 資料進行更新,您可以訪問只有管理員才可訪問的 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,上面還有一個例子。

  要知道在 Session 或 Application 對象中緩衝大的數組不是一個好的做法。在訪問數組的任何元素之前,指令碼語言的文法要求必須臨時複製整個數組。例如,如果將由字串組成的有 100,000 個元素的數組(該數組將美國郵遞區號映射到當地的氣象站)緩衝在 Application 對象中,ASP 必須先將所有的 100,000 個氣象站複製到臨時數組中,然後才能提取一個字串。在這種情況下,用自訂方法建立一個自訂群組件來儲存氣象站 - 或使用一個詞典組件會更好。

  再警告大家一下,不要將嬰兒與洗澡水一起倒掉:數組能快速查尋和儲存在記憶體中是鄰近的關鍵資料對。索引一個詞典比索引一個數組要慢得多。應針對您的實際情況,選擇提供最佳效能的資料結構。

技巧 3:將資料和 HTML 緩衝在 Web 服務器的磁碟上

  有時,資料可能太多,無法都緩衝在記憶體中。“太多”只是一個說法,這要看您想消耗多少記憶體,以及需緩衝的項目數和檢索這些項目的頻率。在任何情況下,如果資料太多而無法都緩衝在記憶體中,則考慮將資料以文本或 XML 檔案快取在 Web 服務器的硬碟上。可以同時將資料緩衝在磁碟和記憶體中,為您的網站建立最適宜的緩衝策略。

  注意當測量單個 ASP 頁的效能時,檢索磁碟上的資料可能不一定要比從資料庫檢索資料更快。但緩衝會降低資料庫和網路上的負載。在高負載的情況下,這樣做可大大改善總體輸送量。當緩衝開銷很大的查詢結果(如多表聯結或複合預存程序)或大的結果集時,這是非常有效。與往常一樣,要測試一下幾種方案的優劣。

  ASP 和 COM 提供一些建立基於磁碟的緩衝方案的工具。ADO 記錄集 Save() 和 Open() 函數儲存和裝載磁碟中的記錄集。可以使用這些方法重新編寫上面 Application 資料緩衝技巧中的程式碼範例,用檔案的 Save() 代替寫到 Application 對象中的代碼。

  有一些其它組件可以用於檔案:

  Scripting.FileSystemObject 可使您建立、讀和寫檔案。
  與 Internet Explorer 一起提供的 Microsoft&reg; XML 解析器 (MSXML) 支援儲存和裝載 XML 文檔。
  LookupTable 對象(例如,用在 MSN 上)是從磁碟裝載簡單列表的最好選擇。
  最後,應考慮將資料的表示緩衝在磁碟上,而不是資料本身。預先轉換的 HTML 可以用 .htm 或 .asp 檔案儲存體在磁碟上,超級連結可以直接指向這些檔案。可以使用商用工具,如 XBuilder,或 Microsoft&reg; SQL Server Internet 發布功能將產生 HTML 的過程自動化。或者,您可以將 HTML 程式碼片斷放在 .asp 檔案中。還可以使用 FileSystemObject 從磁碟讀取 HTML 檔案,或使用 XML 儘早轉換。

技巧 4:避免將非敏捷的組件緩衝在 Application 或 Session 對象中

  儘管將資料緩衝在 Application 或 Session 對象中是一個好的做法,但緩衝 COM 物件卻有嚴重的陷阱。通常,人們傾向於將經常使用的 COM 物件緩衝到 Application 或 Session 對象中。很遺憾,許多 COM 物件(包括所有以 Visual Basic 6.0 或更低版本編寫的對象)當儲存在 Application 或 Session 對象時,會引起嚴重的瓶頸。

  具體來講,當任何不敏捷的組件緩衝在 Session 或 Application 對象時,將引起效能瓶頸。敏捷的組件是被標記為 ThreadingModel=Both 的組件,它聚集 Free-threaded marshaler (FTM);或被標記為 ThreadingModel=Neutral 的組件。(Neutral 模型是 Windows&reg; 2000 和 COM+ 的新增模型。) 下列組件不是敏捷的:

  自由線程的組件(除非它們聚集 FTM)。
  Apartment 執行緒元件。
  單執行緒元件。
  配置的組件(Microsoft Transaction Server (MTS)/COM+ 庫和伺服器程式包/應用程式)不是敏捷的,除非它們是 Neutral 線程。Apartment 執行緒元件和其它非敏捷的組件在頁範圍內是最適合的(即,它們在單個 ASP 頁上建立和銷毀)。

  在 IIS 4.0 中,被標記為 ThreadingModel=Both 的組件被認為是敏捷的。在 IIS 5.0 中,只有這一點還不夠。組件必須不僅被標記 Both,還必須聚集 FTM。有關敏捷性的文章講述了如何使以 Active Template Library 編寫的 C++ 組件聚集 FTM。要注意如果組件緩衝介面指標,那麼那些指標本身必須是敏捷的,或必須儲存在 COM 共用介面表 (GIT) 中。如果您不能重新編譯 Both 執行緒元件以聚集 FTM,那麼您可以將組件標記為 ThreadingModel=Neutral。或者,如果您不想讓 IIS 執行敏捷性檢查(因此,您可以允許非敏捷的組件儲存在 Application 或 Session 範圍中),您可以在設定資料庫中將 AspTrackThreadingModel 設定為 True。不建議更改 AspTrackThreadingModel。

  如果您想將以 Server.CreateObject 建立的非敏捷的組件儲存在 Application 對象中,IIS 5.0 將出現一個錯誤。您可以在 Global.asa 中使用 <object runat=server scope=application ...> 避免這一錯誤,但不建議這樣做,因為這會導致彙集和序列化,關於這一點將在下面講述。

  如果您緩衝非敏捷的組件會出現什麼毛病?緩衝在 Session 對象中的非敏捷的組件將 Session 鎖定於 ASP 工作者線程。ASP 維護一個工作者線程池來處理請求。通常情況下,一個新請求總是由第一個可用的工作者線程來處理。如果 Session 被鎖定於一個線程,那麼請求必須等到其相關的線程可用為止。這裡有一個類比,也許會有所協助:您去一家超級市場,挑選了一些商品,並在 #_3 收款台付款。其後,每當您在那家超級市場為商品付款時,您總是必須在 #_3 收款台付款,即使其它收款台前排隊的人較少或者沒有人排隊,也是如此。

  將非敏捷的組件儲存在 Application 範圍對效能的影響甚至更壞。ASP 必須建立一個特殊的線程運行儲存在 Application 範圍中的非敏捷組件。這會有兩個結果:所有調用都必須彙集到此線程,且所有調用都排成長隊。“彙集”的意思是參數必須儲存在記憶體的共用地區;執行一個開銷很大的到特殊線程的環境切換;動作項目的方法;將結果彙集到共用地區;執行另一個開銷很大的環境切換,將控制返回到原始的線程。“序列化”意思是指每次只運行一個方法。兩個不同的 ASP 工作者線程不能同時在共用組件上執行多個方法。這樣就杜絕了並發性,特別是在多處理器電腦上。更糟的是,所有非敏捷的 Application 範圍的組件共用一個線程(主機 STA),因此序列化的影響甚至更顯著。

  如之奈何?下面是一些一般的規則。如果您使用 Visual Basic (6.0) 或更早版本編寫對象,那麼不要將它們緩衝在 Application 或 Session 對象中。如果您不知道對象的執行緒模式,不要緩衝它。不要緩衝非敏捷的對象,而應在每個頁面建立和釋放它們。對象直接在 ASP 工作者線程上運行,因此沒有彙集或序列化。如果 COM 物件在 IIS 伺服器上運行,且如果它們不花長時間初始化和刪除,效能尚可。注意單線程對象不應該這樣使用。小心 - VB 可建立單線程對象!如果您必須這樣使用單線程對象(如 Microsoft Excel 試算表),別指望會有很高的輸送量。

  當 ADO 被標記為自由線程,ADO 記錄集可以安全地緩衝。要將 ADO 標記為自由線程,使用 Makfre15.bat 檔案,該檔案通常位於目錄 \\Program Files\Common\System\ADO 中。

  警告 如果您使用 Microsoft Access 作為資料庫,不應將 ADO 標記為自由線程的。ADO 記錄集也必須切斷串連。一般來說,如果您不能控制網站中的 ADO 配置(例如,您是一個獨立的軟體廠商 [ISV],向管理他們自己的配置客戶銷售 Web 應用程式),最好不要緩衝記錄集。

  詞典組件也是敏捷的對象。LookupTable 從資料檔案中裝載其資料,可用於組合框資料和配置資訊。Duwamish Books 中的 PageCache 對象可提供詞典文法,Caprock Dictionary 也可提供。這些對象或其派生對象可以構成有效緩衝策略的基礎。注意 Scripting.Dictionary 對象不是敏捷的,不應該儲存在 Application 或 Session 範圍中。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.