共用方式為


效能概觀

更新:2007 年 11 月

效能可以是網站或專案成功的關鍵因素。本主題提供改善網站效能的方針,以及最佳做法文件的連結。

這個主題包含:

  • 最佳作法

  • 背景

  • 程式碼範例

最佳作法

下列清單提供 Microsoft 網站資源的連結,這些資源說明 ASP.NET 網站效能的整體最佳做法。

回到頁首

背景

這一節將列出您可用來協助將 ASP.NET Web 應用程式之效能最大化的技術。這些方針將分別於下列各節中進行討論:

  • 網頁和伺服器控制項處理

  • 狀態管理

  • 資料存取

  • Web 應用程式

  • 程式碼撰寫實務

網頁和伺服器控制項處理

下列方針將建議有效地使用 ASP.NET Web 網頁和控制項的方法。

  • 避免與伺服器間不必要的往返:有些情況下,可以使用 ASP.NET AJAX 和部分網頁呈現,在瀏覽器中完成工作,而不需要執行完整頁面的回傳。例如,在將使用者輸入的內容送出至伺服器之前,您可以使用 ASP.NET AJAX 功能來驗證瀏覽器中使用者輸入的內容。如需詳細資訊,請參閱 ASP.NET AJAX 概觀網頁局部呈現概觀

  • 一般而言,如果不需要將要驗證或寫入至資料存放區的資訊轉送至伺服器,則可藉由避免與伺服器間的往返,來提高網頁的效能,進而改善使用者感受。

  • 如果您要開發自訂的伺服器控制項,則可考慮將它們設計為針對部分功能呈現用戶端指令碼。這樣可以大幅降低傳送資訊至 Web 伺服器的次數。如需詳細資訊,請參閱開發自訂的 ASP.NET 伺服器控制項使用 Microsoft AJAX Library 建立自訂用戶端指令碼

  • 使用 Page 物件的 IsPostBack 屬性以避免不必要的處理:如果只有在第一次要求網頁時需要執行程式碼,則應避免每次回傳時都執行該程式碼。您可以測試 IsPostBack 屬性,根據該網頁是否是回應伺服器控制項事件而產生的,而有條件地執行程式碼。

  • 除非有特別的原因需要關閉緩衝功能,否則請開啟它:停用 ASP.NET Web 網頁的緩衝,會造成明顯的效能成本。如需詳細資訊,請參閱 Buffer 屬性。

  • 使用 Server 物件的 Transfer 方法或使用跨網頁張貼以在相同應用程式的 ASP.NET 網頁之間重新導向:如需詳細資訊,請參閱將使用者重新導向至另一網頁

狀態管理

下列方針會建議有效進行狀態管理的方法。

  • 只有在需要時才儲存伺服器控制項檢視狀態:檢視狀態會讓伺服器控制項在往返時重新填入屬性值,而不需要您撰寫程式碼。然而,檢視狀態會影響效能和頁面大小,因為檢視狀態會在隱藏的表單欄位中,來回傳遞給伺服器。如果在每次往返時將伺服器控制項繫結至資料,則因為會用資料繫結 (Data Binding) 期間的新值來取代控制項的值,所以儲存的檢視狀態並不怎麼有用。在那種情況下,停用檢視狀態會儲存處理時間,並減少網頁的大小。

    依照預設,檢視狀態將會對所有伺服器控制項啟用。若要停用控制項的檢視狀態,請將控制項的 EnableViewState 屬性設為 false (如下列範例所示):

    <asp:datagrid EnableViewState="false" datasource="..." 
       />
    

    您也可以使用 @ Page 指示詞,停用網頁的檢視狀態。

    <%@ Page EnableViewState="false" %>
    

    這在網頁不需要回傳處理時很有用處:

    注意事項:

    @ Control 指示詞中也支援 EnableViewState 屬性 (Attribute),以指定是否啟用使用者控制項的檢視狀態。

    若要分析網頁檢視狀態的大小,請在 @ Page 指示詞中設定 trace="true",啟用網頁追蹤。在追蹤輸出中,檢查 [控制階層架構] 表格的 [Viewstate] 欄位。如需詳細資訊,請參閱 ASP.NET 追蹤概觀

  • 除非必要,否則避免使用檢視狀態加密:檢視狀態加密 (Encryption) 會讓使用者無法讀取隱藏之檢視狀態表單欄位中的檢視狀態值。例如,如果網頁包括 GridView 控制項,此控制項是為了協調記錄的更新而維護 DataKeyNames 屬性中的識別項欄位,則您可能會想要加密檢視狀態。由於您不想要讓使用者看見識別項,所以可以加密檢視狀態。不過,加密對於初始化具有固定的效能成本,而且具有取決於所加密之檢視狀態大小的額外成本。每次載入網頁時都會執行加密。因此,第一次要求網頁和每次回傳期間,都會發生相同的效能影響。

  • 在不使用工作階段狀態時停用它:若要停用網頁的工作階段狀態,請將 @ Page 指示詞中的 EnableSessionState 屬性設為 false (如下列範例所示):

    <%@ Page EnableSessionState="false" %>
    
    注意事項:

    如果網頁需要存取工作階段變數,但不會建立或修改它們,請將 @ Page 指示詞中的 EnableSessionState 屬性設為 ReadOnly。

    您也應停用 ASP.NET Web 服務方法的工作階段狀態。如需詳細資訊,請參閱 ASP.NET 應用程式服務概觀

    若要停用應用程式的工作階段狀態,請在應用程式之 Web.config 檔案的 SessionState 區段中,將 Mode 屬性設為 Off (如下列範例所示):

    <sessionState mode="Off" />
    
  • 選擇符合應用程式需要的適當工作階段狀態提供者:ASP.NET 提供多種方式來儲存應用程式的工作階段資料,其中包括同處理序 (In-Process) 工作階段狀態、跨處理序 (Out-Of-Process) 工作階段狀態 (如 Windows 服務),以及 SQL Server 資料庫中的跨處理序工作階段狀態 (您也可以建立自訂工作階段狀態提供者,將工作階段資料儲存在您指定的資料存放區中)。上述每個方法都有其優點,但同處理序工作階段狀態顯然是最快速的方法。如果工作階段狀態只是用於在工作階段狀態中存放小量資料,請使用同處理序提供者。如果要將應用程式調整成跨多個處理器或跨多台電腦,或想要在重新啟動伺服器或處理序時保留工作階段資料,則請使用跨處理序工作階段狀態選項。如需詳細資訊,請參閱 ASP.NET 工作階段狀態概觀

資料存取

下列方針會建議在應用程式中有效進行資料存取的方法。

  • 使用 SQL Server 和預存程序進行資料存取:建議使用 SQL Server 做為資料儲存,以建立高效能且可擴充的 Web 應用程式。使用 Managed SQL Server 提供者時,透過使用已編譯的預存程序代替 SQL 命令,可以獲得額外的效能提升。如需詳細資訊,請參閱設定參數和參數資料型別 (ADO.NET)

  • 使用 SqlDataReader 類別做為快速單向捲動檢視 (Forward-only) 的資料游標SqlDataReader 類別會建立從 SQL Server 資料庫擷取的單向捲動檢視唯讀資料流。SqlDataReader 類別會使用 SQL Server 的原生 (Native) 網路資料傳輸格式,從資料庫連接中直接讀取資料。如果可行的話,請使用 SqlDataReader 類別,因為該類別提供的效能比 DataSet 類別好。例如,繫結資料控制項至 SqlDataSource 控制項時,如果將 DataSourceMode 屬性設為 DataReader,即可達到較佳的效能 (不過,資料讀取器支援的功能比 DataSet 模式少)。SqlDataReader 類別會實作 IEnumerable 介面,可讓您將伺服器控制項繫結至該介面。如需詳細資訊,請參閱 SqlDataReader 類別和 使用 ASP.NET 存取資料

  • 盡可能快取資料和網頁輸出:如果需要動態計算每個網頁要求的網頁或資料輸出,請使用 ASP.NET 快取。如果可能,請將網頁和資料要求設計為進行快取,尤其是網站流量大的位置。適當地使用快取所提高的網站效能會高於使用 .NET Framework 中的任何其他功能。

    當您使用 ASP.NET 快取時,請遵循下列方針。首先,不要快取太多項目,因為每個快取項目都需要伺服器記憶體。例如,請勿快取易於重新計算或鮮少使用的項目。第二,不要指派過短的到期時間給快取的項目。快速過期的項目會造成額外的清除程式碼和記憶體回收行程工作。使用與 [ASP.NET 應用程式] 效能物件關聯的 [Cache Total Turnover Rate] 效能計數器,即可監視因項目到期所產生的快取重組。高重組率可能代表問題,特別是項目在過期前移除的時候(這個狀況有時稱為記憶體壓力)。

    如需如何快取網頁輸出和資料要求的詳細資訊,請參閱 ASP.NET 快取概觀

  • 適當地使用 SQL 快取相依性:為了從 SQL Server 快取資料,ASP.NET 會依據您所使用的 SQL Server 版本,支援資料表架構的輪詢和查詢告知。所有 SQL Server 版本都支援資料表架構的輪詢。在資料表架構的輪詢中,如果資料表中有任何資料變更,所有相依於資料表的快取項目就會失效。這樣可能會導致快取中出現不必要的重組。對於經常變更的資料表而言,不建議使用資料表架構的輪詢。例如,不常變更的目錄資料表就會建議使用資料表架構的輪詢。對於經常更新的訂單資料表則不建議使用。

    SQL Server 2005 (含) 以後版本支援查詢告知。查詢告知使用 SQL 查詢來偵測目標資料列組中的變更。這樣可以減少當資料表變更時所傳送的告知次數。查詢告知提供的效能比資料表架構輪詢更好。不過它無法縮放為數千筆查詢。

    如需 SQL 快取相依性的詳細資訊,請參閱逐步解說:將 ASP.NET 輸出快取功能與 SQL Server 搭配使用以 SqlCacheDependency 類別在 ASP.NET 中快取

  • 使用資料來源分頁和排序而非 UI (使用者介面) 分頁和排序:資料控制項 (例如 DetailsViewGridView) 的 UI 分頁功能可搭配支援 ICollection 介面的任何資料來源物件使用。對於每個分頁作業而言,資料控制項會查詢整個資料集合的資料來源、選取要顯示的一個或多個資料列,接著捨棄其餘資料。

    如果資料來源控制項實作 DataSourceView 而且 CanPage 屬性傳回 true,則資料控制項會使用資料來源分頁而不是 UI 分頁。在這種情況下,資料控制項只會要求每個顯示頁面所需的資料列。因此,資料來源分頁會比 UI 分頁更有效率。標準 ASP.NET 控制項中,只有 ObjectDataSourceLinqDataSource 資料來源控制項支援資料來源分頁。若要啟用其他資料來源控制項的資料來源分頁,您可以從您要使用的資料來源控制項進行繼承,然後修改它的行為。

  • 使用 Timestamp 資料行搭配 LinqDataSource 控制項進行並行控制:如果 SQL Server 資料庫資料表未包含 Timestamp 資料行 (一種 SQL Server 資料型別),則 LinqDataSource 控制項會將原始資料值儲存在網頁中以檢查資料並行性。LINQ to SQL 在更新或刪除資料之前,會根據資料庫檢查原始值。如果資料錄包含許多資料行或很大的資料行值,這種方法便會建立大型的 Web 網頁。如果記錄中包含您不想在頁面上公開的資料,它也會顯示安全性風險。如果資料庫資料表具有 Timestamp 資料行,則 LinqDataSource 控制項只會儲存時間戳記值以供未來比較之用。LINQ to SQL 透過判斷原始時間戳記是否符合資料表中目前的時間戳記值,來檢查資料的一致性。如需時間戳記的詳細資訊,請參閱 MSDN 網站上的 timestamp (Transact-SQL)

  • 權衡事件驗證的安全性優點與效能成本:衍生自 System.Web.UI.WebControlsSystem.Web.UI.HtmlControls 類別的控制項可以驗證控制項所呈現之使用者介面中產生的事件。這樣可以協助防止控制項回應假冒的事件告知。例如,藉由使用事件驗證,DetailsView 控制項可以防止惡意使用者進行 Delete 呼叫 (控制項中原本不支援),並在刪除資料中操作控制項。不過,事件驗證具有某些效能成本。您可以使用 EnableEventValidation 組態項目和 RegisterForEventValidation 方法,控制事件驗證。驗證的成本取決於網頁上的控制項數目,而且位於少數百分比範圍中。

    安全性注意事項:

    強烈建議您不要停用事件告知。如果您停用事件驗證,請先確定不會建構會對應用程式造成不當影響的回傳。

  • 使用 SqlDataSource 快取、排序和篩選:如果 SqlDataSource 控制項的 DataSourceMode 屬性設定為 DataSetSqlDataSource 控制項就能夠快取查詢的結果集 (Result Set)。SqlDataSource 控制項的篩選和排序作業就能接著使用快取的資料。如果您快取整個資料集,並且使用 FilterExpressionSortParameterName 屬性來排序和篩選,應用程式執行的速度就會更快。接下來,每當使用者在 UI 中排序或篩選資料時,資料來源控制項就能避免在 SQL 查詢中使用 Where 和 Sort By 子句。

Web 應用程式

下列方針會建議一些讓 Web 應用程式整體有效率運作的方法。

  • 先行編譯網站:Web 應用程式會在第一次要求資源 (例如 ASP.NET Web 網頁) 時進行批次編譯。如果沒有編譯應用程式中的網頁,批次編譯 (Compilation) 則會按區塊 (Chunk) 對目錄中的所有網頁進行編譯,進而改善磁碟和記憶體使用量。您可以使用 ASP.NET 編譯工具 (Aspnet_compiler.exe) 來先行編譯 Web 應用程式。如果是就地編譯,編譯工具則會呼叫 ASP.NET 執行階段,以使用者要求網站中的網頁時的相同方式來編譯網站。您可以對 Web 應用程式進行先行編譯,使 UI 標記維持不變,或者對網頁進行先行編譯,使原始程式碼不受變更。如需詳細資訊,請參閱 HOW TO:先行編譯 ASP.NET 網站

  • 停用偵錯模式:在部署實際執行應用程式或進行任何效能度量之前,一定要停用偵錯模式。如果啟用偵錯模式,則應用程式的效能可能會降低。如需如何設定偵錯模式的詳細資訊,請參閱編輯 ASP.NET 組態檔

  • 調整 Web 伺服器電腦和特定應用程式的組態檔:ASP.NET 的預設組態可以啟用最多功能的組合以及最常見的案例。您可以根據所使用的功能來變更部分預設的組態設定,以提高應用程式的效能。下列清單包含您應考慮的組態變更:

    • 僅針對需要驗證的應用程式啟用驗證:根據預設,ASP.NET 應用程式的驗證模式為 Windows 或整合式 NTLM。在大部分的情況中,最好是停用 Machine.config 檔中的驗證,並在需要驗證之應用程式的 Web.config 檔中啟用驗證。

    • 將應用程式設定為適當的要求和回應編碼設定:ASP.NET 的預設編碼方式是 UTF-8。如果您的應用程式只使用 ASCII 字元,請將應用程式設定為 ASCII,能些微地改善效能。

    • 考慮停用應用程式的 AutoEventWireup:將 Web.config 檔中的 AutoEventWireup 屬性設為 false,可避免根據名稱符合將網頁事件繫結至方法 (例如,Page_Load)。這可讓網頁效能得到一點改善。若要處理網頁事件,請使用下列其中一種策略。第一項策略是覆寫方法。例如,在撰寫頁面載入事件的程式碼時,您可以覆寫 Page 物件的 OnLoad 方法 (請務必呼叫基底方法來確保所有事件都已引發)。第二項策略是使用 Handles 關鍵字 (在 Visual Basic 中) 或使用委派連接 (在 C# 中),繫結至事件。

    • 移除要求處理管線中的未使用模組:在 Web 伺服器電腦之 Machine.config 檔的 HttpModules 節點中,所有功能預設都會保持使用中狀態。依照應用程式所使用的功能,您可以從要求管線移除不要使用的模組,而稍微地提升效能。檢視每個模組及其功能,並依您的需要加以自訂。例如,如果未在應用程式中使用工作階段狀態和輸出快取,則可從 HttpModules 清單中移除這些功能的模組。

  • 在 Internet Information Services 5.0 上執行 Web 應用程式跨處理序:根據預設,IIS 5.0 上的 ASP.NET 將會使用跨處理序的背景工作處理序來服務要求。這個功能已微調以得到快速輸送量。因為在跨處理序背景工作處理序中執行 ASP.NET 有其功能和益處,所以建議您在實際執行網站上使用這種方法。

  • 定期回收處理序:您應該定期回收處理序,以獲得穩定性和效能。經過一段長時間後,具有記憶體遺漏 (Memory Leak) 和錯誤的資源會影響 Web 伺服器輸送量,而回收處理序會清除這類問題的記憶體。然而,您應該在定期回收的需求與過常回收之間取得平衡,因為停止背景工作處理序、重新載入網頁和重新取得資源和資料的代價,可能會高過回收的益處。

    在 Windows Server 2003 和 IIS 6.0 上執行的 ASP.NET Web 應用程式不需要調整處理序模型,因為 ASP.NET 會使用 IIS 6.0 處理序模型設定。

  • 針對應用程式正確設定每個背景工作處理序的執行緒數目:ASP.NET 的要求架構會嘗試在執行要求的執行緒數目與可用資源之間取得平衡。此架構只容許與可用 CPU 能耐相等的並行執行要求數目。這個技術即是 Thread Gating。然而,有些情況下 Thread-Gating 演算法無法正常運作。您可以在 Windows 效能監視器中,使用與 [ASP.NET 應用程式] 效能物件關聯的 [Pipeline Instance Count] 效能計數器,監視 Thread Gating。

    ASP.NET 網頁呼叫外部資源時 (例如存取資料庫或處理 ASP.NET Web 服務要求時),該網頁要求一般會停止,直到外部資源回應。這樣可以釋出 CPU 以處理其他執行緒。如果其他要求正在等候處理,且執行緒集區有可用執行緒,則會開始處理等待的要求。結果是 ASP.NET 背景工作處理序或應用程式集區中有許多並行執行要求和許多等待中執行緒,這樣可能會妨礙 Web 伺服器的輸送量,進而對效能造成負面影響。

    若要降低對效能的影響,您可以手動設定處理序中執行緒數目的限制。若要這麼做,請變更 Machine.config 檔中 processModel 區段的 MaxWorkerThreadsMaxIOThreads 屬性。

    注意事項:

    背景工作執行緒適合處理 ASP.NET 要求。IO 執行緒則是用於服務檔案、資料庫或 ASP.NET Web 服務的資料。

    您指派給處理序模型屬性的值代表處理序中每個 CPU 之每種執行緒類型的最大數目。對於有兩個處理器的電腦,最大數目是設定值的兩倍。對於有四個處理器的電腦而言,最大值為設定值的四倍。預設設定適用於具有一個處理器和兩個處理器的電腦,但是對於具有兩個以上處理器的電腦而言,處理序中若有 100 或 200 個執行緒,對效能而言是有害無益的。處理序中如果有太多執行緒,速度會變慢。伺服器必須執行額外的內容切換,因而造成作業系統將 CPU 循環花費在維護執行緒而不是處理要求上。您可以執行應用程式的效能測試,用以決定適當的執行緒數目。

  • 若是大量依賴外部資源的應用程式,請在多處理器電腦上啟用 Web Gardening:ASP.NET 處理序模型協助啟用多處理器電腦上的延展性 (Scalability),方法是將工作散發給數個處理序、每個 CPU 都有一個處理序,而每個處理序的處理器相似性是設定給 CPU。這種技術有時也稱為「Web Gardening」。如果 Web 應用程式大量使用外部資源,就能從 Web Gardening 獲得好處。例如,如果應用程式使用資料庫伺服器或呼叫具有外部相依性的 COM 物件,就可能會因此而受益。然而,在您針對實際執行網站啟用 Web Gardening 之前,應該先測試 Web 應用程式在 Web 處理序區 (Web Garden) 中的效能。

程式碼撰寫實務

下列方針會建議撰寫有效程式碼的方法。

  • 不要依賴程式碼中的例外狀況:例外狀況會大幅降低效能,所以應避免使用它們做為控制一般程式流程的方法。請盡可能在程式碼中加入邏輯,用來偵測和處理會造成例外狀況的條件。以程式碼進行偵測的一般案例包括 null 的檢查、將字串剖析為數值,以及在算術運算之前檢查特定值。下列範例顯示可能會造成例外狀況的程式碼,並顯示用來測試條件的替代程式碼。兩個範例都會產生相同結果。

    // This is not recommended.
    try {
       result = 100 / num;
    }
    catch (Exception e) {
      result = 0;
    }
    
    // This is preferred.
    if (num != 0)
       result = 100 / num;
    else
      result = 0;
    
    ' This is not recommended.
    Try
       result = 100 / num
    Catch (e As Exception)
      result = 0
    End Try
    
    ' This is preferred.
    If Not (num = 0)
       result = 100 / num
    Else
      result = 0
    End If
    

程式碼範例

使用說明和逐步解說主題

HOW TO:檢視電腦上可用的 ASP.NET 效能計數器

HOW TO:先行編譯 ASP.NET 網站

逐步解說:將 ASP.NET 輸出快取功能與 SQL Server 搭配使用

逐步解說:建立具備 AJAX 功能的網站

回到頁首

請參閱

概念

監視 ASP.NET 應用程式效能

ASP.NET 的效能計數器

效能的設計和組態

使用服務之應用程式的效能考量

加入 AJAX 和用戶端功能

參考

回到頁首

其他資源

ASP.NET 快取