改善 ASP 效能的訣竅

訣竅 1:將經常使用的資料快取處理在 Web 伺服器上
典型的 ASP 頁面從後端資料存放區中取出資料,然後將結果轉換成超文字標記語言 (HTML)。無論資料庫的速度為何,從記憶體中取出資料一定比從後端資料存放區中取出資料快得多。從本機硬碟讀取資料通常也比從資料庫中取出資料更快。因此,您通常可以將資料快取處理在 Web 伺服器上 (存放在記憶體或磁片中),來提高效能。

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

不經常變更的資料是很好的快取候選對象,因為您不必擔心一段時間後同步處理該資料與資料庫的問題。組合方塊清單、參照表、DHTML 剪輯資料、可擴充標記語言 (XML) 字串、功能表項目和網站設定變數 (包括資料來源名稱 (DSN)、Internet 通訊協定 (IP) 位址和 Web 路徑) 都是很好的快取處理對象。注意您可以快取資料的「呈現方式」,而不是資料本身。如果 ASP 頁面很少變更,且快取的虛耗空間也很大 (例如,整本產品目錄),則應考慮預先生成 HTML,而不是在回應每個請求時轉換。

應將資料快取在哪裏?有哪些快取策略?通常,資料被快取處理在 Web 伺服器的記憶體或磁碟中。下面兩個訣竅說明了這些選擇。

 

 訣竅 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 物件存放在應用程式或工作階段領域中的危險性。

當您將資料存放在應用程式或工作階段領域時,資料將存留在那裏,直到您以程式改變它、工作階段過期,或 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 個氣象站複製到暫時陣列中,然後才能提取一個字串。在這種情況下,用自訂方法建立一個自訂元件來存放區氣象站 - 或使用字典元件會更好。

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

 

 訣竅 3:將資料和 HTML 快取在 Web 伺服器的磁碟上
有時,資料可能太多,無法都快取在記憶體中。「太多」只是說法,這要看您想消耗多少記憶體,以及需快取的項目數量和取出這些項目的頻率。在任何情況下,如果資料太多,無法都快取在記憶體中,則應考慮將資料以文字或 XML 檔案快取在 Web 伺服器的硬碟上。您可以同時將資料快取在磁碟和記憶體中,為您的網站建立最佳的快取策略。

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

ASP 和 COM 提供一些建立磁碟式快取方案的工具。ADO 記錄集 Save() 和 Open() 函數儲存和載入磁碟中的記錄集。您可以使用這些方法重新編寫上面的應用程式資料快取訣竅中的程式碼範例,用檔案的 Save() 代替寫到應用程式物件中的程式碼。

以下是可以用於檔案的其它元件:

Scripting.FileSystemObject 可使您建立、讀取和寫入檔案。
Internet Explorer 隨附的 Microsoft® XML 分析程式 MSXML 支援儲存和載入 XML 文件。
LookupTable 物件 (範例,用在 MSN 上) 是從磁碟載入簡單清單的最好選擇。
最後,應考慮將資料的表示快取在磁碟上,而不是資料本身。預先轉換的 HTML 可以用 .htm 或 .asp 檔案存放在磁碟上;超連結可以直接指向這些檔案。您可以使用商用工具如 XBuilder,或 Microsoft® SQL Server™ Internet 發行功能將產生 HTML 的程序自動化。或者,您可以將 HTML 程式碼片斷放在 .asp 檔案中。還可以使用 FileSystemObject 從磁碟讀取 HTML 檔案,或使用 XML 盡早轉換。

 


 訣竅 4:避免將非敏捷的元件快取在應用程式或工作階段物件中
盡管將資料快取在應用程式或工作階段物件中是一個好的做法,但快取「COM 物件」卻有嚴重的陷阱。通常,人們傾向於將經常使用的 COM 物件快取到應用程式或工作階段物件。很遺憾,許多 COM 物件 (包括所有以 Visual Basic 6.0 或舊版編寫的物件) 當存放在應用程式或工作階段物件時,會引起嚴重的瓶頸。

特別是,當任何不敏捷的元件被快取在工作階段或應用程式物件時,將引起效能瓶頸。敏捷的元件是被標記為 ThreadingModel=Both 的元件,它彙總無限制執行緒封送 (FTM),或被標記為 ThreadingModel=Neutral 的元件。(Neutral 模型是 Windows® 2000 和 COM+ 的新模型。) 下列元件不是敏捷的:

無限制執行緒的元件 (除非它們彙總 FTM)。
Apartment-threaded 元件。
單一執行緒元件。
組態的元件 (Microsoft Transaction Server (MTS)/COM+ 程式庫和伺服器套件/應用程式) 不是敏捷的,除非它們是 Neutral-threarded。Apartment-threaded 元件和其它非敏捷的元件在畫面領域內最適合 (即它們在單一 ASP 頁面上建立和終結)。

在 IIS 4.0 中,被標記為 ThreadingModel=Both 的元件被認為是敏捷的。在 IIS 5.0 中,只有這一點還不夠。元件必須不僅被標記成 Both,還必須彙總 FTM。有關敏捷性的文章描述如何使以 Active Template Library 編寫的 C++ 元件彙總 FTM。要注意如果元件快取介面指標,那麼那些指標本身必須是敏捷的,或必須存放在 COM Global Interface Table (GIT) 中。如果您不能重新編譯 Both-threaded 元件以彙總 FTM,那麼您可以將元件標記為 ThreadingModel=Neutral。或者,如果您不想讓 IIS 執行敏捷性檢查 (因此,您可以允許非敏捷的元件存放在應用程式或工作階段領域),您可以在 metabase 中將 AspTrackThreadingModel 設定為 True。不建議變更 AspTrackThreadingModel。

如果您想將以 Server.CreateObject 建立的非敏捷的元件存放在應用程式物件中,IIS 5.0 將出現一個錯誤。您可以在 Global.asa 中使用 <object runat=server scope=Application ...> 避免這個錯誤,但不建議這樣做,因為這會導致封送和序列化,關於這一點將在下面說明。

如果您快取非敏捷的元件會出現什麼問題?快取在工作階段物件中的非敏捷的元件將工作階段鎖定於 ASP 背景工作執行緒。ASP 維護服務所請求的背景工作執行緒集區。通常情況下,新請求總是由第一個可用的背景工作執行緒來處理。如果工作階段被鎖定於一個執行緒,那麼請求必須等待其相關的執行緒可用時才可以執行。以下的類比也許會有幫助:您去一家超級市場,挑選了一些商品,並在 #3 收銀台付款。其後,每當您在那家超級市場付款時,您總是必須在 #3 收銀台付款,即使其它收銀台前等候的人較少或者沒有人等候。

將非敏捷的元件存放在應用程式領域對效能的影響甚至更大。ASP 必須建立一個特殊的執行緒以執行非敏捷的、應用程式領域的元件。這會有兩個結果:所有呼叫都必須封送到此執行緒,且所有呼叫都序列化。「封送」的意思是:參數必須存放在記憶體的共用區域,設定昂貴的特殊執行緒的內容參數,執行元件的方法,結果被封送到共用區域,另一個昂貴的內容參數將控制傳回到原始的執行緒。「序列化」的意思是指每次只執行一個方法。兩個不同的 ASP 背景工作執行緒無法同時在共用元件上執行多個方法。這樣可以杜絕並行性,特別是在多處理器電腦上。更糟的是,所有非敏捷的應用程式領域的元件共用一個執行緒 (主機 STA),因此序列化的影響甚至更顯著。

糊塗了吧?下面是一些一般規則。如果您使用 Visual Basic (6.0) 或更早版本編寫物件,那麼不要將它們快取在應用程式或工作階段物件中。如果您不知道物件的執行緒模型,不要快取它。不要快取非敏捷的物件,而應在每個頁面建立和釋放它們。物件直接在 ASP 背景工作執行緒上執行,因此沒有封送或序列化。如果 COM 物件在 IIS box 上執行,且如果它們不花長時間起始化和終結,則效能尚可。注意單一執行緒物件不應該這樣使用。小心 - 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 物件不是敏捷的,不應該存放在應用程式或工作階段領域中。

 

 訣竅 5:不要將資料庫連線快取在應用程式或工作階段物件中
快取 ADO 連線通常是一個不好的策略。如果一個連線物件存放在應用程式物件中並在所有的畫面中使用,那麼所有畫面將爭用這個連線。如果連線物件存放在 ASP 工作階段物件中,那麼將為每個使用者建立資料庫連線。這就會使連線集區的優點無效,並給 Web 伺服器和資料庫帶來不必要的負載。

不要快取資料庫連線,而是在使用 ADO 的每個 ASP 頁面中建立和終結 ADO 物件。因為 IIS 內嵌資料庫連線集區,這樣做是有效率的。更準確地說,IIS 自動啟用 OLEDB 和 ODBC 連線集區。這就能確保在每個頁面上建立和終結連線將是有效率的。

因為連線的記錄集存放到資料庫連線的參照,所以您不應將連線的記錄集快取在應用程式或工作階段物件中。但是,您可以安全地快取中斷連線的記錄集,它們不存放資料連線的參照。要中斷記錄集連線,執行下面的兩個步驟:

Set rs = Server.CreateObject(?ADODB.RecordSet?)
rs.CursorLocation = adUseClient ' step 1

' Populate the recordset with data
rs.Open strQuery, strProv

' Now disconnect the recordset from the data provider and data source
rs.ActiveConnection = Nothing ' step 2


有關連線集區的詳細資訊,可以在 ADO 和 SQL Server 參考資料中找到。

 

 訣竅 6:合理地使用工作階段物件
現在我們已經採納快取在應用程式和工作階段中的優點,而現在將建議避免使用工作階段物件。正如下面將討論的,當與忙碌的網站一起使用時,工作階段有幾個缺點。「忙碌」的意思一般是指一秒鐘要求幾百畫面或成千上萬同時使用者的網站。這個訣竅對於必須水平調適的網站 - 即那些利用多台伺服器以處理負載或建置容錯的網站 - 甚至更重要。對於較小的網站,諸如 Intranet 網站,工作階段的方便性是值得花成本的。

簡單地回顧一下,ASP 自動為每個存取 Web 伺服器的使用者建立一個工作階段。每個工作階段大約需要 10 KB 的記憶體虛耗空間 (除了存放在工作階段中的任何資料),這就使所有的請求都減慢。在設定的逾時時段 (通常是 20 分鐘) 結束以前,工作階段一直保持有效。

工作階段最大的問題不是效能,而是調適性。工作階段不跨越幾台 Web 伺服器,一旦在一台伺服器上建立工作階段,其資料就留在那兒。這表示如果您在一個 Web 伺服器群使用工作階段,您必須設計一個策略,將每個使用者請求永遠導向到使用者工作階段所在的那台伺服器上。這被稱為將使用者「stick」在 Web 伺服器上。「Sticky 工作階段」一詞就是從這裏衍生而來的。如果 Web 伺服器當機,「stuck」使用者將遺失他們的工作階段狀態,因為工作階段不是存留到磁碟上。

建置 sticky 工作階段的策略包括硬體和軟體解決方案。諸如 Windows 2000 Advanced Server 中的網路負載平衡和 Cisco 的 Local Director 之類的解決方案都可以建置 sticky 工作階段,代價是要損失一定程度的調適性。這些解決方案是不完善的。不建議此時部署您自己的軟體解決方案 (我們過去常常使用 ISAPI 篩選器和 URL 轉換等等)。

應用程式物件也不跨越多台伺服器,如果您必須跨越 Web 伺服器群共用和更新應用程式資料,您必須使用後端資料庫。但是,唯讀應用程式資料在 Web 伺服器群中仍是有用的。

如果只是因為增加執行時間 (處理錯誤後移轉和伺服器維護),大多數關鍵工作網站至少需部署兩台 Web 伺服器。因此,在設計關鍵工作應用程式時,必須建置「sticky 工作階段」,或幹脆避免工作階段,以及任何其它將使用者狀態存放在單一 Web 伺服器上的狀態管理技術。

如果您不使用工作階段,一定要將它們關閉。您可以透過 Internet Services Manager 來為應用程式關閉工作階段 (參閱 ISM 文件)。如果決定使用工作階段,您可以採用一些方法減輕它們對效能的影響。

您可以將不需要工作階段的內容 (如說明畫面、參觀者區域等等) 移到另一個已關閉工作階段的 ASP 應用程式中。您可以逐頁為在指定頁面中不需要工作階段物件的 ASP 提供提示,使用下面放在 ASP 頁面頂部的指令:

<% @EnableSessionState=False %>


使用這一指令有一個很好的理由是工作階段會為框架組建立一個有趣的問題。ASP 保證任何時候都只執行工作階段的一個請求。這樣就確保如果瀏覽器為一個使用者請求多個畫面,一次只有一個 ASP 請求接觸工作階段,避免了當存取工作階段物件時發生的多執行緒問題。很遺憾,結果一個框架組中的所有畫面將以序列化方式顯示,一個接一個,而不是同時顯示。使用者可能必須等候很長的時間,才能看到所有的框架。該故事的寓意:如果某些框架組畫面不依靠工作階段,一定要使用 @EnableSessionState=False 指令告訴 ASP。

許多管理工作階段狀態的方法可以作為使用工作階段物件的取代辦法。對於少量的狀態 (少於 4 KB),我們通常建議使用 Cookies、QueryString 變數和隱式變數。對於更大資料量,如購物籃車,後端資料庫是最適合的選擇。有關 Web 伺服器群中的狀態管理技術的文章很多。有關詳細資訊,請參閱工作階段狀態參考資料。

 

 訣竅 7: 將程式碼封裝在 COM 物件中
如果您有許多 VBScript 或 JScript,您可以經常將程式碼移到編譯的 COM 物件中,來改善效能。編譯過的程式碼通常比解釋的程式碼執行得更快。編譯過的 COM 物件可以透過「早期連結」存取其它 COM 物件,「早期連結」是比指令碼使用的「晚期連結」更加有效地呼叫 COM 物件的方法。

將程式碼封裝在 COM 物件中還有一些優點 (除效能之外):

COM 物件有利於將表示邏輯與業務邏輯分開。
COM 物件可以保證程式碼重複使用。
許多開發人員發現以 VB、C++ 或 Visual J++ 編寫的程式碼比 ASP 更容易除錯。
COM 物件也有缺點,包括初始開發時間和需要不同的程式設計技巧。注意封裝「少」量的 ASP 可能引起效能損失,而不是效能改進。這種情況通常在少量的 ASP 程式碼被壓縮到 COM 物件時發生。在這種情況下,建立和呼叫 COM 物件的系統虛耗空間超過編譯的程式碼的優點。應反覆地試驗以確定什麼樣的 ASP 指令碼和 COM 物件程式碼的組合產生最好的效能。注意 Microsoft 的 Windows 2000/IIS 5.0 中比 Windows NT® 4.0/IIS 4.0 在指令碼和 ADO 效能方面有了很大的改進。因此,隨著 IIS 5.0 的推出,編譯程式碼比 ASP 程式碼的效能優勢有所降低。

有關在 ASP 中使用 COM 的優點和缺點的詳細討論,參閱 ASP Component Guidelines and Programming Distributed Applications with and Microsoft Visual Basic 6.0。如果您真的要部署 COM 元件,對它們進行強度測試特別重要。事實上,理所當然應對所有的 ASP 應用程式進行強度測試。

 

 訣竅 8:遲一點取得資源,早一點釋放資源
這裏是一個小訣竅供您參考。一般來說,最好遲一點取得資源,早一點釋放資源。這適用於 COM 物件以及檔案控制碼和其它資源。

ADO 連線和記錄集是這種最佳化方法的主要候選物件。當您使用完記錄集,例如在顯示一個資料表及其資料之後,應立即釋放它,而不是等到畫面的結束。將 VBScript 變數設定為 Nothing 是最好的做法。不要讓記錄集超出領域之外。而且,要釋放任何相關的指令或連線物件。(在將記錄集或連線設定為 = Nothing 之前,不要忘記呼叫 Close()。) 這會縮短資料庫必須為您準備資源的時間,並盡快釋放資料庫到連線集區的連線。

 

 訣竅 9:跨程序執行用效能交換可靠性
ASP 和 MTS/COM+ 兩者都有組態選項,可使您權衡可靠性和效能。當建立和部署應用程式時,應知道如何權衡兩者的效能。

ASP 選項
您可以設定 ASP 應用程式以三種方法之一執行。在 IIS 5.0 中,引入了「隔離等級」這個術語以描述這些選項。這三個隔離等級分別是低、中和高級:

低級隔離。所有 IIS 的版本都有支援,且是最快的。它在 Inetinfo.exe 中執行 ASP,Inetinfo.exe 是主要 IIS 程序。如果 ASP 應用程式崩潰,IIS 也會崩潰。(要在 IIS 4.0 下重新啟動 IIS,Web 網站管理員應使用諸如 InetMon 之類的工具監視網站,如果伺服器發生故障,應啟動批次檔以重新啟動伺服器。IIS 5.0 引入了可靠的重新啟動,能將發生故障的伺服器自動重新啟動。)
中級隔離。IIS 5.0 引入了這個新的級別,它被稱為跨程序等級,因為 ASP 在 IIS 程序之外執行。在中級隔離中,被設定為作為中級隔離執行的所有 ASP 應用程式都共用一個程序空間。這就減少在一台伺服器執行多個跨程序 ASP 應用程式所必需的程序的數量。中級隔離是 IIS 5.0 中的預設隔離級別。
高級隔離。在 IIS 4.0 和 IIS 5.0 中有支援,高級隔離也是跨程序的。如果 ASP 損壞,Web 伺服器並不會當機。下次 ASP 請求時,ASP 應用程式就會自動重新啟動。在高級隔離中,設定為作為高級隔離執行的每個 ASP 應用程式都在其自有程序空間中執行。這樣做可保護 ASP 應用程式彼此之間不相互干擾。其缺點是它要求每個 ASP 應用程式都要有一個單獨的程序。當在一台伺服器上必須執行許多應用程式時,系統虛耗空間就會大大增加。
哪個選項最好呢?在 IIS 4.0 中,跨程序執行將顯著降低效能。在 IIS 5.0 中,做了許多改進,將跨程序執行 ASP 應用程式所產生的成本降到最低限度。事實上,在絕大多數測試中,IIS 5.0 中的 ASP 跨程序應用程式比 IIS 4.0 中的同程序應用程式執行得更快。不管怎樣,同程序 (低隔離等級)在兩個平台上仍產生最好的效能。但是,如果存取率相對較低或最大輸送量較低,您就不會看到低隔離等級有多大的優點。因此,在您每一 Web 伺服器每秒鐘需要數百或成千上萬畫面時,才會覺得有必要設定低隔離等級。與往常一樣,應對多種組態進行測試並確定您樂意採取哪一種權衡方案。

注意 當您執行 ASP 跨程序應用程式時,(中級或高級隔離),它們在 NT4 中的 MTS 和在 Windows 2000 中的 COM+ 中執行。即,在 NT4 中它們在 Mtx.exe 中執行;而在 Windows 2000 中,它們在 DllHost.exe 中執行。您可以在工作管理員中看到這些程序在執行。您還可以看到 IIS 如何設定跨程序 ASP 應用程式的 MTS 套件或 COM+ 應用程式。

COM 選項
雖然與 ASP 選項不完全類似,COM 元件也有三種組態選項。COM 元件可以是「未設定的」、「設定為程式庫應用程式」,或「設定為伺服器應用程式」。「未設定的」意思是指元件沒有向 COM+ 註冊。元件將在呼叫程式的程序空間執行,那就是說,它們是「同程序」。程式庫應用程式也是同程序,但使用 COM+ 的服務,包括安全、交易和內容支援。伺服器應用程式被設定為在它們自有程序空間內執行。

您可以看到未設定的元件比程式庫應用程式略有一些優勢。您還可能看到程式庫應用程式比伺服器應用程式的效能優點更大。這是因為程式庫應用程式與 ASP 在同一程序執行,而伺服器應用程式在它們的自有程序執行。程序間的呼叫比同程序呼叫虛耗空間更大。而且,當在程序之間傳遞諸如記錄集之類的資料時,必須在兩個程序之間複製所有的資料。

陷阱!當使用 COM 伺服器應用程式時,如果您在 ASP 和 COM 之間傳遞物件,要確保物件建置「按值封送」或 MBV。建置 MBV 的物件將它們自己從一個程序複製到另一個程序。這比採用物件仍在建立者的程序中而另外一個程序反覆地呼叫建立程序以使用該物件的方法好。中斷連線的 ADO 記錄集將「按值封送」,連線的記錄集則不會。Scripting.Dictionary 不執行 MBV 並不在程序之間傳遞。最後,VB 程式編寫人員請注意:MBV 不透過傳遞參數 ByVal 獲得。MBV 由原始的元件作者建置。

怎麼辦?
如果讓我們建議一個權衡效能與可靠性的合理組態,它們應是如下的組態:

在 IIS 4.0 中,使用 ASP 低隔離等級,使用 MTS 伺服器套裝軟體。
在 IIS 5.0 上,使用 ASP 的中隔離等級,並使用 COM+ 程式庫應用程式。
這些是非常一般的原則,主機公司一般情況下以中或高隔離等級執行 ASP,而單一用途的 Web 伺服器可以以低隔離級執行。權衡各種利弊,並自己決定哪個組態更能符合您的需要。

 

 訣竅 10:使用 Option Explicit
在 .asp 檔案中應使用 Option Explicit。此指令放在 .asp 檔案的最上面,強制開發人員宣告將使用到的所有變數。許多程式設計師認為這種方法對於除錯應用程式很有幫助,因為這種方法避免打錯變數名稱和誤建新變數的可能性 (例如,將 MyXMLString=) 錯寫成 MyXLMString=...。

更重要的一點也許是,宣告的變數比未宣告的變數更快。由此,script 在執行時每次用到未宣告的變數時,依名稱參照變數。另一方面,宣告的變數卻有順序,按照編譯時間或執行時間。然後,宣告的變數都按此順序參照。因為 Option Explicit 強制變數宣告,能確保宣告所有變數,因此存取的速度也很快。

 

 訣竅 11:在副程式和函數中使用區域變數
區域變數是那些在副程式和函數內宣告的變數。在函數或副程式內,區域變數存取比全域變數存取更快。區域變數的使用也會使程式碼更清楚,因此應盡量使用區域變數。


 訣竅 12:將經常使用的資料複製到指令碼變數中
當存取 ASP 中的 COM 物件時,應將經常使用的物件資料複製到指令碼變數中。這樣做就會減少 COM 方法呼叫,因為 COM 方法呼叫與存取指令碼變數相比,虛耗空間相對較大。當存取 Collection 和 Dictionary 物件時,這種技術也會減少很大的查尋。

一般來說,如果您打算存取物件資料一次以上,那麼就應將資料放到 script 變數中。這種最佳化的主要目標是 Request 變數 (Form 和 QueryString 變數)。例如,您的網站可傳遞一個名為 UserID 的 QueryString 變數。假設此 UserID 在指定畫面上被參照 12 次。您可以無須呼叫 Request(?UserID?) 12 次,而是在 ASP 畫面最上面將 UserID 指派到一個變數。然後在該畫面自始至終使用該變數。這樣就可以節省 11 次 COM 方法呼叫。

實際上,存取 COM 內容或方法的並沒有那麼大。下面舉一個例子,說明某個相當常見的程式碼 (從語法上而言):

Foo.bar.blah.baz = Foo.bar.blah.qaz(1)
If Foo.bar.blah.zaq = Foo.bar.blah.abc Then ' ...


當此程式碼執行時,下面是發生的情況:

變數 Foo 被解析為全域物件。
變數 bar 被解析為 Foo 的成員。這就是一次 COM 方法呼叫。
變數 blah 被解析為 Foo.bar 的成員。這又是一次 COM 方法呼叫。
變數 qaz 被解析為 foo.bar.blah 的成員。是的,這還是一次 COM 方法呼叫。
呼叫 Foo.bar.blah.quaz(1)。又是一次 COM 方法呼叫。懂了嗎?
再次執行步驟 1 至步驟 3 以解析 baz。系統並不知道呼叫 qaz 是否改變物件模型,因此必須再次執行步驟 1 至 3 以解析 baz。
將 baz 解析為 Foo.bar.blah 的成員。賦予屬性。
再次執行步驟 1 至步驟 3 以解析 zaq。
再次執行步驟 1 至步驟 3 以解析 abc。
正如您可看到的,效率相當差 (而且很慢)。以 VBScript 寫此程式碼的快速方法是:

Set myobj = Foo.bar.blah ' do the resolution of blah ONCE
Myobj.baz = myobj.qaz(1)
If Myobj.zaq = Myobj.abc Then '...


如果您使用 VBScript 5.0 或更新版本,您可以使用 With 陳述式寫此程式碼:

With Foo.bar.blah
.baz = .qaz(1)
If .zaq = .abc Then '...
..
End With


注意此訣竅也適用於 VB 程式設計。

 

 訣竅 13:避免重新確定陣列的維數
應盡量避免 Redim 陣列。就效能而言,如果電腦的實體記憶體大小有限,最好將陣列的初始維數設定為其最不利的情況 - 或將維數設定為其最佳的情況,然後再按需要重新確定維數。這並非意味著,如果知道您不需要記憶體時,就隨便分配幾 MB 的記憶體。

下面的程式碼顯示不當使用 Dim 和 Redim的情形。

<%
Dim MyArray()
Redim MyArray(2)
MyArray(0) = ?hello?
MyArray(1) = ?good-bye?
MyArray(2) = ?farewell?
..
' some other code where you end up needing more space happens, then ..
Redim Preserve MyArray(5)
MyArray(3) = ?more stuff?
MyArray(4) = ?even more stuff?
MyArray(5) = ?yet more stuff?
%>


最好一開始就將陣列的初始大小 Dim 正確 (在本例中為 5),而不是使 Redim 陣列更大。您可能浪費一些記憶體 (如果您沒有使用所有的元件),但獲得的好處是速度變得更快。

 


 訣竅 14:使用回應緩衝
您可以藉由啟動「回應緩衝」來將值得輸出的整個畫面緩衝起來。這樣可以將寫到瀏覽器的量減到最少,因而改善總體效能。每個寫入作業都要很大的虛耗空間 (在 IIS 中以及在透過網路傳送的資料量方面),因此寫入作業越少越好。由於其啟動慢和使用 Nagling 演算法 (用來減輕網路塞車情況),TCP/IP 在傳送一些大的資料區塊時比必須傳送許多小的資料區塊時的效率高得多。

回應緩衝有兩個啟動方法。第一種,您可以使用 Internet Services Manager 啟動整個應用程式的回應緩衝。我們建議採用這種方法,在 IIS 4.0 和 IIS 5.0 中在預設情況下為啟動新的 ASP 應用程式的回應緩衝。第二種,可以在每個 ASP 畫面的接近頂端的地方放入下面的程式碼,以啟動回應緩衝:

<% Response.Buffer = True %>


此行程式碼必須在任何回應資料被寫到瀏覽器之前執行 (即,在任何 HTML 出現在 ASP 指令碼之前以及使用 Response.Cookies 集合設定任何 Cookies 之前)。一般來說,最好啟動整個應用程式的回應緩衝。這樣,您就不必在每個畫面最上面寫入上述的程式碼。

Response.Flush
關於回應緩衝有一個常見的抱怨,就是使用者感覺到 ASP 頁面的回應速度較差 (即使整個回應時間有所改進),因為他們必須等待整個畫面產生,然後才能開始看到東西。對於執行時間長的畫面,您可以用設定 Response.Buffer = False,取消回應緩衝。但是,比較好的策略是利用 Response.Flush 方法。這種方法將 ASP 轉換的所有 HTML 送到瀏覽器。例如,在轉換有 1,000 資料列的資料表中的 100 資料列之後,ASP 可以呼叫 Response.Flush 強制將轉換的結果送到瀏覽器,這樣可以讓使用者在其餘的資料列準備好之前看到頭 100 列。這種技術可以將回應緩衝與瀏覽器逐漸顯示資料完美地結合在一起。

(注意在上面的 1,000 資料列資料表的範例中,許多瀏覽器在看到關閉 </table> 標記之前不會開始顯示資料表。檢查您的目標瀏覽器是否有支援。為避免這種情況,將資料表分成多個具有較少資料列的資料表,並在每個資料表之後呼叫 Response.Flush。較新版本的 Internet Explorer 在表格完全下載之前就開始顯示資料表,如果您指定資料表欄寬,顯示速度就會特別快,這樣做可避免強制 Internet Explorer 透過測量每個儲存格的內容寬度來計算欄寬。)

另一個關於回應緩衝的常見的抱怨是,當產生非常大的畫面時,將佔用許多伺服器記憶體。撇開產生大畫面的方法不談,這種問題也可以透過巧妙使用 Response.Flush 來加以解決。


訣竅 15:批次處理內嵌 Script 和 Response.Write 陳述式
VBScript 語法 <% = expression %> 將「expression」的值寫到 ASP 輸出資料流中。如果未啟動回應緩衝,那麼每個陳述式都會通過網路以許多小的封包將資料寫到瀏覽器中。這樣速度很慢。而且,分散少量的 script 和 HTML 會引起 script 引擎和 HTML 之間的切換,因而降低效能。因此,使用下面的訣竅:使用 Response.Write 呼叫代替緊密連結的內嵌運算式。例如,在下面的範例中,在每一列的每一欄位對回應資料流有一次寫入作業,每一列在 VBScript 和 HTML 之間有許多切換:

<table>
<% For Each fld in rs.Fields %>
<th><% = fld.Name %></th>
<%
Next
While Not rs.EOF
%>
<tr>
<% For Each fld in rs.Fields %>
<td><% = fld.Value %></td>
<% Next
</tr>
<% rs.MoveNext
Wend %>
</table>


下面的程式碼會更有效率,每一資料列對答覆資料流有一次寫入作業。所有的程式碼都包含在一個 VBScript 區塊內:

<table>
<%
For each fld in rs.Fields
Response.Write (?<th>? & fld.Name & ?</th>? & vbCrLf)
Next
While Not rs.EOF
Response.Write (?<tr>?)
For Each fld in rs.Fields %>
Response.Write(?<td>? & fld.Value & ?</td>? & vbCrLf)
Next
Response.Write ?</tr>?
Wend
%>
</table>


當取消回應緩衝時,這個訣竅的影響會更大。最好啟動回應緩衝,然後看看批次處理 Response.Write 是否有助於提高效能。

(在這個特殊的範例中,建立資料表主體的巢狀迴圈 (While Not rs.EOF...) 可以用仔細建構的 GetString 的呼叫來取代。)

 


 訣竅 16:在開始長途旅行之前使用 Response.IsClientConnected
如果使用者沒有耐心,他們可能會在您開始執行他們的請求之前就會放棄 ASP 畫面。如果他們按一下重新整理或移到伺服器上的另一個畫面,在 ASP 請求佇列的結尾就有一個新的請求等候,在佇列中間有一個中斷連線的請求。當伺服器的負載很高時 (因此請求佇列就會更長,回應時間也會相應地變長),就會經常發生這種情況,這樣只能使情況變得更糟。如果使用者不再連線,執行 ASP 頁面 (特別是慢的、大的 ASP 頁面) 已沒有任何意義。您可以使用 Response.IsClientConnected 內容檢查這個情況。如果它傳回 False,則應呼叫 Response.End 並放棄畫面的其餘部分。事實上,IIS 5.0 已將這個做法編碼 - 每當 ASP 即將執行新請求時,它就會檢查請求在佇列中已等候多長時間。如果已經在那裏等候多於 3 秒鐘,ASP 將檢查用戶端是否仍處於連線狀態,如果沒有連線,就立即停止請求。您可以在 metabase 中使用 AspQueueConnectionTestTime 設定來調整 3 秒的逾時。

如果畫面要花很長時間才能執行完,您可能想要不時地檢查 Response.IsClientConnected。當啟動回應緩衝時,最好不時地執行 Response.Flush,讓使用者知道正在發生什麼事。

注意 在 IIS 4.0 上,除非先執行 Response.Write,否則 Response.IsClientConnected 就不能正常運作。如果啟動緩衝,您也必須執行 Response.Flush。在 IIS 5.0 上,卻沒有必要這樣做,- Response.IsClientConnected 運作正常。在任何情況下,Response.IsClientConnected 都會有一些成本,因此只有在一個作業至少要花 (比方說) 500 毫秒時 (如果您想維持每秒鐘數十頁的輸送量,這是一個很長的時間) 才使用它。經驗證明,不要每次重複執行緊密迴圈時都呼叫它,如顯示資料表的許多資料列時 - 每隔二十或五十資料列可能比較合適。

 

 訣竅 17:使用 <OBJECT> 標記列舉物件
如果要參照不在所有的程式碼路徑 (特別是伺服器或應用程式領域的物件) 中使用的物件,使用 Global.asa 中 <object runat=server id=objname> 標記來宣告物件,而不使用 Server.CreateObject 方法。Server.CreateObject 能立即建立物件。如果以後不再使用該物件,您就浪費了資源。<object id=objname> 標記宣告 objname,但在其方法或屬性第一次使用以前,不會建立 objname。

這又是一個惰性評估的範例。

 

 訣竅 18: 利用瀏覽器的驗證功能
現代的瀏覽器對如 XML、DHTML、Java 附屬應用程式和遠端資料服務等功能有進階支援。盡可能使用這些功能。所有的這些技術都可以執行用戶端驗證和資料快取,節省到 Web 伺服器的來回傳輸。如果您在執行智慧型瀏覽器,此瀏覽器就能為您進行一些驗證 (例如,在執行 POST 之前,檢查信用卡總和檢查碼是否有效)。另外,盡可能使用這一功能。透過減少用戶端/伺服器之間的來回傳輸,可降低對 Web 伺服器的負載,並能減少網路傳輸量 (雖然傳送到瀏覽器的第一個頁面可能比較大) 及伺服器存取的任何後端資源。此外,使用者將不必像往常一樣讀取新頁面,因此感覺會好一些。這樣做並不意味著您可以不進行伺服器端驗證 - 您應該一定要進行伺服器端驗證。這樣做可以防止由於某種原因 (如駭客或瀏覽器不執行用戶端驗證常式) 用戶端產生錯誤的資料。

人們已經進行了大量的工作,開發「與瀏覽器無關」的 HTML。正是由於這種憂慮,開發人員不願再使用可以改善效能、大眾化的瀏覽器功能。對於一些必須關心瀏覽器「連線」問題的真正高效能網站,一個好的策略是最佳化頁面,使其適應大眾化的瀏覽器。使用瀏覽器功能元件,可以在 ASP 中輕鬆地偵測到瀏覽器功能。Microsoft FrontPage 等工具有助於設計適合於瀏覽器和指定 HTML 版本的程式碼。若需詳細的討論資訊,請參閱 When is Better Worse?Weighing the Technology Trade-Offs。

 


 訣竅 19:對於 ADO 和其它元件使用 TypeLib 宣告
當使用 ADO 時,開發人員經常加入 adovbs.txt ,以存取 ADO 的各種常數。在要使用常數的每個畫面中必須包含此檔案。此常數檔案相當大,為每個 ASP 畫面的編譯時間和 script 大小增加許多虛耗空間。

IIS 5.0 引入連結到元件型別程式庫的功能。這可使您參照類型程式庫一次,就可以用在每個 ASP 畫面上。每個頁面不需要因編譯常數檔案而降低,且元件開發人員不必建立在 ASP 上使用的 VBScript#include 檔案。

要存取 ADO TypeLib,將下面的陳述式放在 Global.asa 中。

<!-- METADATA NAME=?Microsoft ActiveX Data Objects 2.5 Library?
TYPE=?TypeLib? UUID=?{00000205-0000-0010-8000-00AA006D2EA4}? -->


<!-- METADATA TYPE=?TypeLib?
FILE=?C:\Program Files\Common Files\system\ado\msado15.dll? -->

 


 訣竅 20:避免在迴圈中使用字串並列
許多人在迴圈中建立如下所示的字串:

s = ?<table>? & vbCrLf
For Each fld in rs.Fields
s = s & ? <th>? & fld.Name & ?</th> ?
Next

While Not rs.EOF
s = s & vbCrLf & ? <tr>?
For Each fld in rs.Fields
s = s & ? <td>? & fld.Value & ?</td> ?
Next
s = s & ? </tr>?
rs.MoveNext
Wend

s = s & vbCrLf & ?</table>? & vbCrLf
Response.Write s


這種方法會出現一些問題。第一個問題是反覆並列字串需要花二次方的時間,更簡單地說,執行這種迴圈所花的時間與記錄數乘以欄位數所得值的平方成正比。舉一個簡單的例子就可以更清楚地說明這個問題。

s = ??
For i = Asc(?A?) to Asc(?Z?)
s = s & Chr(i)
Next


在第一個重複項目中,您取得了包含一個字元的字串 ?A?。在第二個重複項目中,VBScript 必須重新配置字串並將兩個字元 (?AB?) 複製到 s 中。在第三個重複項目中,它還必須再次重新配置 s 並將三個字元複製到 s 中。在 N 個 (第 26 個) 重複項目中,它必須重新配置並將 N 個字元複製到 s 中。總共就是 1+2+3+...+N,即 N*(N+1)/2 次複製。

在上面的記錄集範例中,如果有 100 個記錄和 5 個欄位,內迴圈將執行 100*5 = 500 次,所有的複製和重新配置所花的時間與 500*500 = 250,000 成正比。這對於中等大小的記錄集來說複製作業太多了。

在本範例中,程式碼可以用 Response.Write() 或內嵌指令碼 (<% = fld.Value %> ) 替代字串並列來改進。如果啟動回應緩衝的話 (應該要啟動),這樣做就會更快,因為 Response.Write 只將資料附加到回應緩衝的結尾。並不涉及重新配置,因此效率很高。

在將 ADO 記錄集轉換為 HTML 表格的特殊情況下,應考慮使用 GetRows 或 GetString。

如果在 JScript 中並列字串,特別建議使用 += 運算子,即使用 s += ?some string?,而不使用 s = s + ? some string?。

 

 訣竅 21:啟用瀏覽器和 Proxy 快取
在預設情況下,ASP 取消在瀏覽器和 Proxy 中的快取。這是有意義的,因為就本質而言,ASP 畫面是動態的,上面不斷有潛在的對時間敏感的資訊。如果頁面不要求在每個檢視上重新顯示,您應啟動瀏覽器和 Proxy 快取。這可使瀏覽器和 Proxy 在您可以控制時間長短的一定時間內使用頁面的「快取」副本。快取可以大大地減輕伺服器上的負載,並可改善使用者的使用經驗。

哪一種動態頁面可作為要快取的頁面呢?下面舉一些範例:

天氣預報頁面,在此頁面上,每隔 5 分鐘更新一次天氣預報。
列出新聞項目或新聞稿的首頁,一天更新兩次。
共同基金績效清單,在此清單中,基本統計資料每隔幾小時更新一次。
注意,在使用瀏覽器或 Proxy 快取的情況下,Web 伺服器上記錄的存取次數變少了。如果您想準確地測量所有整頁檢視,或張貼通告,您就不希望使用瀏覽器和 Proxy 快取。

瀏覽器快取由 HTTP「過期」標頭控制,該標頭由 Web 伺服器傳送給瀏覽器。ASP 提供兩個簡單的機制傳送此標頭。要設定畫面使其過多少分鐘後到期,則應設定 Response.Expires 屬性。下面的範例告訴瀏覽器內容在 10 分鐘內過期:

<% Response.Expires = 10 %>


若將 Response.Expires 設定為負數或 0,則停用快取。請確定要使用大的負數,如 -1000 (略多於一天),以避免伺服器和瀏覽器小時鐘之間不相符。第二個屬性 Response.ExpiresAbsolute 可以讓您設定內容過期的具體時間:

<% Response.ExpiresAbsolute = #May 31,2001 13:30:15# %>


您可以不使用 Response 物件設定過期時間,而將 <META> 標記寫進 HTML,通常寫在 HTML 檔案的 <HEAD> 部分。有些瀏覽器將遵照此指令,而 Proxy 則不然。

<META HTTP-EQUIV=?Expires? VALUE=?May 31,2001 13:30:15?>


最後,您可以使用 Response.CacheControl 屬性,指示其內容是否可以讓 HTTP Proxy 快取。若將此屬性設定為「Public」,Proxy 就可以快取此內容。

<% Response.CacheControl = ?Public? %>


在預設情況下,此屬性被設定為「Private」。注意,對於顯示某使用者特定資料的畫面,不應啟動 Proxy 快取,因為 Proxy 可能會提供使用者屬於其他使用者的畫面。

 

 訣竅 22:盡可能使用 Server.Transfer 代替 Response.Redirect
Response.Redirect 讓瀏覽器請求另一個畫面。此函數常用來將使用者重新導向到登入或錯誤畫面。因為重新導向強制請求新畫面,結果是瀏覽器必須到 Web 伺服器往返兩次,且 Web 伺服器必須多處理一個請求。IIS 5.0 引入一個新的函數 Server.Transfer,它將執行轉移到同一台伺服器上的另一個 ASP 畫面。這樣可以避免額外的瀏覽器/Web 伺服器的往返,進而改善總體系統效能以及對使用者的回應時間。檢 查「重新導向」中的「新的方向」,上面應該是 Server.Transfer 和 Server.Execute。

另請參閱 Leveraging ASP in IIS 5.0 以了解 IIS 5.0 和 ASP 3.0 新功能的完整清單。

 

 訣竅 23:在目錄 URL 中使用反斜線
一個相關的訣竅是確定在指向目錄的 URL 中使用反斜線 (/)。如果您省略了反斜線,瀏覽器就會向伺服器發出請求,只是為了告訴伺服器,它在請求目錄。瀏覽器就會發出第二個請求,將斜線附加到 URL 後面,此時,伺服器才能以該目錄的預設文件或目錄清單 (如果沒有預設文件且啟用目錄瀏覽的話) 回應。附加斜線可省去第一個無用的往返。為便於使用者閱讀,可以省略顯示名稱中的反斜線。

例如,寫:

<a href=?http://msdn.microsoft.com/workshop/? title=?MSDN Web
Workshop?>http://msdn.microsoft.com/workshop</a>


這也適用於指向 Web 網站上首頁的 URL:使用下面的:<a href=?http://msdn.microsoft.com/?>,而不使用 <a href=?http://msdn.microsoft.com?>。

 

 訣竅 24:避免使用伺服器變數
存取伺服器變數會使 Web 網站向伺服器發出一個特殊請求,並收集所有伺服器變數,而不只是您請求的那個變數。這種情況類似於,在發霉的閣樓上,在一個資料夾中尋找某個檔案。當您想要找那個檔案時,您必須去閣樓上,先找到檔案夾,然後才能找到這份檔案。當您請求伺服器變數時,發生的情況是一樣的 - 您第一次請求伺服器變數時,就會使效能受到影響。後續對其它伺服器變數的請求不會對效能產生影響。

決不要存取非限定的 Request 物件 (例如,)。對於不在 Request.Cookies、Request.Form、Request.QueryString 或 Request.ClientCertificate 中的項目,則用隱式呼叫 Request.ServerVariables。Request.ServerVariables 集合比其它集合慢得多。

 

 訣竅 25:升級到最新和最出色的
系統元件是恆定的,我們建議您將它們升級到最新和最好的組態。最好升級到 Windows 2000 (因此,也應升級到 IIS 5.0、ADO 2.5、MSXML 2.5、Internet Explorer 5.0、VBScript 5.1 和 JScript 5.1)。在多處理器電腦上,建置 IIS 5.0 和 ADO 2.5 可顯著改善效能。在 Windows 2000 下,ASP 可以調適到四個處理器或更多,而在 IIS 4.0 下,ASP 的調適性不能超出兩個處理器。在應用程式中使用的指令碼和 ADO 越多,升級到 Windows 2000 之後,效能的改善就會越多。

如果目前還不能升級到 Windows 2000,您可以升級到 SQL Server、ADO、VBScript 和 JScript、MSXML、Internet Explorer 和 NT 4 Service Packs 的最新版本。它們均可提高效能和可靠性。

 

 訣竅 26:最佳化 Web 伺服器
有多種 IIS 最佳化參數可以改善網站效能。例如,對於 IIS 4.0,我們常常發現,增加 ASPProcessorThreadMax 參數 (參閱 IIS 文件) 可以有很大的好處,特別是在傾向於等待後端資源 (如資料庫) 或其它中間產品 (如 screen-scraper) 的網站上。在 IIS 5.0 中,您可能發現啟動 ASP Thread Gating 比尋找一個 AspProcessorThreadMax 最佳設定效率更高,這一點現在已為大家所熟知。

有關較好的參考資料,參閱下面的最佳化 IIS。

最佳的組態設定取決於 (其中一些因素) 應用程式的程式碼、執行所在的系統硬體和用戶端工作負載。找到最佳設定的唯一方法是進行效能測試,這是我們下一個訣竅中所要討論的。

 

 訣竅 27:進行效能測試
正如我們在前面已經講過,效能是一項功能。如果您想要改善網站的效能,那麼要設定效能目標,然後逐步改進,直到達到目標為止。不要因為怕影響專案進展,就不進行任何效能測試。通常,在專案結束時,再作必需的結構調整已經為時太晚,因而導致您的客戶失望。將效能測試作為您日常測試的一部分來進行。您可以對個別元件分別進行效能測試,如針對 ASP 畫面或 COM 物件,或整體測試網站。

許多人使用單一瀏覽器請求畫面,來測試 Web 網站的效能。這樣做就會給您一個感覺,即網站的回應能力很好,但這樣做實際上並不能告訴您在負載下網站的效能如何。

一般情況下,要想準確地測試效能,您需要一個專用的測試環境。此環境應包括硬體,其處理器速度、處理器數量、記憶體、磁碟、網路設定等方面與生產環境的硬體相似。其次,您必須指定用戶端的工作負載:有多少同時的使用者,他們發出請求的頻率,他們點擊畫面的類型等等。如果您沒有網站實際使用情況的資料,您必須估計一下使用的情況。最後,您需要一個可以模擬預期用戶端工作負載的工具。有了這些工具,您就可以開始回答諸如「如果我有 N 個同時的使用者,那麼需要多少伺服器?」之類的問題。您還可以找出出現瓶頸的原因,並以此為目標進行最佳化。

下面列出一些不錯的 Web 強度測試工具。我們強烈建議 Microsoft Web Application Stress (WAS) Toolkit。WAS 可使您記錄測試 script,然後模擬數百或成千上萬個使用者存取 Web 伺服器。WAS 報告很多統計資料,包括每秒鐘的請求數,回應時間分布情況和錯誤計數。WAS 有豐富的用戶端介面和 Web 介面,Web 介面可以讓您進行遠端測試。

 
來源:http://redhat.ecenter.idv.tw/bbs/showthread.php?threadid=11968

 
 

arrow
arrow
    全站熱搜

    sleepingwolf 發表在 痞客邦 留言(0) 人氣()