程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> ASP編程 >> 關於ASP編程 >> 改進性能和樣式的24個ASP 技巧

改進性能和樣式的24個ASP 技巧

編輯:關於ASP編程

簡介

技巧 1:在 Web 服務器上緩存常用數據

技巧 2:在 Application 或 Session 對象中緩存常用數據

技巧 3:在 Web 服務器磁盤上緩存數據和 HTML

技巧 4:避免在 Application 或 Session 對象中緩存非靈活組件

技巧 5:不要在 Application 或 Session 對象中緩存數據庫連接

技巧 6:妙用 Session 對象

技巧 7:在 COM 對象中封裝代碼

技巧 8:晚點獲取資源,早點釋放資源

技巧 9:進程外的執行將犧牲可靠性

技巧 10:顯式使用選項

技巧 11:在子例程和函數中使用局部變量

技巧 12:將常用數據復制到腳本變量

技巧 13:避免重新定義數組

技巧 14:使用響應緩沖

技巧 15:批處理內嵌腳本和 Response.Write 語句

技巧 16:在開始長時間的任務之前先使用 Response.IsClientConnected

技巧 17:使用 <OBJECT> 標記實例化對象

技巧 18:使用 ADO 對象和其他組件的 TypeLib 綁定

技巧 19:利用浏覽器的驗證能力

技巧 20:在循環中避免字符串串聯

技巧 21:啟用浏覽器和代理緩存

技巧 22:盡可能使用 Server.Transfer 替代 Response.Redirect

技巧 23:在目錄 URL 尾部加斜線

技巧 24:避免使用服務器變量


--------------------------------------------------------------------------------

簡介

性能是一個特性。您需要預先設計性能,或是在日後重新編寫應用程序。換句話說,什麼是最大限度優化 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)。無論數據庫的速度如何,從內存檢索數據要比從後端數據庫檢索數據快得多。從本地硬盤讀取數據通常也要比從數據庫檢索數據快得多。因此,通常可以通過在 Web 服務器(在內存或磁盤)上緩存數據來改善性能。

緩存是典型的空間與時間的折衷。如果恰當地緩存數據,您將看到性能會有驚人的提高。為使緩存發揮效力,它必須保持經常重用的數據,而且重新計算這些數據的代價是昂貴的或比較昂貴的。如果緩存充滿了垃圾數據,則是對存儲器的浪費。

不經常變化的數據也是緩存的候選數據,因為您無須擔心數據與數據庫的同步問題。組合框、引用表、DHTML 碎片、可擴展標記語言 (XML) 字符串、菜單項和站點配置變量(包括數據源名稱 (DSN)、Internet 協議 (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

‘' 注意:此處可能有兩個或多個調用。這是可以的,只不過
‘' 產生幾個不必要的取指令罷了(就此有一個工作區)

‘' FetchEmploymentStatusList 函數(不顯示)
‘' 從 DB 中取數據,返回一個數組
d = FetchEmploymentStatusList()

‘' 更新 Application 對象。用 Application.Lock()
‘' 來確保一致的數據
Application.Lock
Application("EmploymentStatusList") = d
Application("Lastupdate") = CStr(Now)
Application.Unlock
End If
End Sub

其他示例,請參閱具有 Application 數據的最快列表框(英文)。

請注意,在 Session 或 Application 對象中緩存大型數組並非上策。在訪問數組元素之前,腳本語言的語法要求建立整個數組的臨時副本。例如,如果在 Application 對象中緩存了將美國郵政編碼映射到本地氣象站的字符串數組,該字符串數組有 100,000 個元素,ASP 在找出一個字符串之前,必須將所有 100,000 個氣象站復制到臨時數組中。在這種情況下,建立帶自定義方法的自定義組件,來存儲氣象站 - 或使用一個字典組件,也許更好。

請不要在倒洗澡水時把孩子一同倒掉,對這種觀點的一個新的注解是:數組提供了對內存中相鄰關鍵-數據對的快速查找和存儲。索引字典比索引數組要慢。您應該根據具體情況選擇能夠提供最佳性能的數據結構。

技巧 3:在 Web 服務器磁盤上緩存數據和 HTML

有時,數據過多不能在內存中進行緩存。"過多"是一種定性的判斷;它取決於打算消耗的內存量,還有緩存項的數量和這些項的檢索頻率。總之,如果有過多的數據要在內存中緩存,請考慮以文本或 XML 文件的形式,在 Web 服務器的硬盤上緩存數據。可以將在磁盤上緩存數據和在內存中緩存數據組合起來,為站點建立最優的緩存策略。

注意,在度量單個 ASP 頁的性能時,在磁盤上檢索數據不一定比從數據庫中檢索數據快。但是,緩存減輕了數據庫和網絡的負荷。在高負荷情況下,這將明顯提高總體通信量。在查詢成本很高時緩存查詢的結果,緩存便非常有效,例如多表聯合或復雜的存儲過程,或緩存大型的結果集。按照慣例,測試競爭方案。

ASP 和 COM 提供了幾種構建磁盤緩存方案的工具。ADO 記錄集的 Save() 和 Open() 函數,保存和加載磁盤上的記錄集。您可以使用這些方法重寫上面 Application 數據緩存技巧中的范例代碼,用 Save() 文件替換向 Application 對象寫入數據的代碼。

還有其他一些處理文件的組件:

Scripting.FileSystemObject 使您能夠創建、讀取和寫入文件。
MSXML 是隨 Internet Explorer 提供的 Microsoft(R) XML 解析器,它支持保存和加載 XML 文檔。
LookupTable 對象(在 MSN 上使用的范例)是從磁盤加載簡單列表的良好選擇。
最後,請考慮在磁盤上緩存數據的表示,而不是數據本身。預制的 HTML 可以作為 .htm 或 .asp 文件存儲在磁盤上;超級鏈接可以直接指向這些文件。可以使用商業工具,如 XBuilder 或 Microsoft(R) SQL Server 的 Internet 發行功能來自動化 HTML 生成過程。另外,可以將 HTML 片段 #include 到 .asp 文件。還可以使用 FileSystemObject 從磁盤讀取 HTML 文件或使用 XML 進行早期調整(英文)。

技巧 4:避免在 Application 或 Session 對象中緩存非靈活組件

雖然在 Application 或 Session 對象中緩存數據是個好主意,但是緩存 COM 對象可能有嚴重缺陷。將常用 COM 對象嵌入 Application 或 Session 對象通常具有吸引力。遺憾的是,很多 COM 對象,包括用 Visual Basic 6.0 或更早版本編寫的 COM 對象,在 Application 或 Session 對象中存儲時將導致嚴重的瓶頸。

特別是任何非靈活組件,在 Session 或 Application 對象中緩存時將導致性能瓶頸。靈活組件是標記為
ThreadingModel=Both
的組件(它聚集了自由線程匯集器 (FTM))或標記為
ThreadingModel=Neutral
的組件(Windows(R) 2000 和 COM+ 中新增的"中性"模型。)下列組件是非靈活的:

自由線程組件(除非它們聚集了 FTM)。
單元線程組件。
單線程組件。
已配置組件(Microsoft Transaction Server (MTS)/COM+ 庫和服務器包/應用程序)為非靈活組件,除非它們是"中性"線程的。單元線程組件和其他非靈活組件最適於在頁作用域工作(也就是說,它們在單個 ASP 頁上創建和銷毀)。

在 IIS 4.0 中,標記為
ThreadingModel=Both
的組件被視為靈活的。在 IIS 5.0 中,這已經不夠了。組件不僅必須標記為 Both,而且還必須聚集 FTM。靈活性文章說明了如何使得用"活動模板庫"編寫的 C++ 組件聚集 FTM。請注意,如果組件緩存接口指針,這些指針本身必須為靈活的、或者必須存儲在"COM 全局接口表 (GIT)"中。如果不能重新編譯 Both 線程組件,使它聚集 FTM,則可以將該組件標記為
ThreadingModel=Neutral
。另外,如果不希望 IIS 進行靈活性檢查(這樣,希望非靈活組件能夠存儲在 Application 或 Session 作用域中),可以在 metabase 中設置
AspTrackThreadingModel

True
。不主張更改
AspTrackThreadingModel

如果試圖在 Application 對象中存儲用
Server.createObject
創建的非靈活組件,IIS 5.0 將產生錯誤。可以通過在 Global.asa 中使用
<object runat=server scope=application ...>
解決該問題,但是不主張這樣做,因為這將導致匯集和串行化,說明如下。

如果緩存非靈活組件,會發生什麼錯誤呢?緩存在 Session 對象中的非靈活組件,將把會話"鎖定"到某個 ASP 工作器線程。ASP 維護著一個工作器線程池,它向請求提供服務。通常,新的請求由第一個可用的工作器線程來處理。如果 Session 被鎖定到某個線程,則該請求將不得不等待它所關聯的線程變為可用。打個比方:您進入一個超市,挑選了一些食品,然後在第 3 號收款台交款。從這以後,每當您在這個超市購買食品,都不得不始終在第 3 號收款台交款,即使是在其他收款台人少或沒人時。

將非靈活組件存儲在 Applicaton 作用域甚至會對性能產生更嚴重的影響。ASP 將不得不創建專用的線程來運行非靈活的、Applicaton 作用域內的組件。這將導致兩種後果:所有調用不得不被匯集到該線程,而且所有調用被串行化。匯集意味著:參數不得不存儲在內存的共享區;對該專用線程執行昂貴的上下文切換;組件的方法被執行;結果匯集到共享區域;以及經過另一個昂貴的上下文切換,使控制權返回原來的線程。串行化意味著所有方法必須一個挨一個地運行(同一時刻只能運行一個方法)。兩個不同的 ASP 工作器線程不可能同時執行共享組件上的方法。這將扼殺並行機制,尤其是在多處理器計算機上。更壞的是,所有非靈活的、Application 作用域內的組件都將共享一個線程("Host 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:不要在 Application 或 Session 對象中緩存數據庫連接

緩存 ADO 連接通常是不好的策略。如果一個 Connection 對象存儲在 Application 中,並在所有頁上使用,那麼所有頁將競爭使用該連接。如果 Connection 對象存儲在 ASP Session 對象中,那麼將為每個用戶創建數據庫連接。這將連接池的好處毀於一旦,並對 Web 服務器和數據庫產生不必要的壓力。

取代緩存數據庫連接的方法是,在每個使用 ADO 的 ASP 頁上創建並取消 ADO 對象。這是個有效的方法,因為 IIS 具有內置的數據庫連接池。更准確的說,IIS 自動啟用 OLEDB 和 ODBC 連接池。這確保了創建並取消每個頁上的連接將是有效的。

由於被連接的記錄集中存儲有對數據庫連接的引用,所以,不應當在 Application 或 Session 對象中緩存被連接的記錄集。但是,可以安全地緩存斷開連接的記錄集,因為它不包含對其數據連接的引用。要斷開記錄集的連接,請執行如下兩個步驟:

Set rs = Server.createObject("ADODB.RecordSet")
rs.CursorLocation = adUseClient ‘' 第 1 步

‘' 植入帶數據的記錄集
rs.Open strQuery, strProv

‘' 現在斷開記錄集同數據提供者和數據源的連接
rs.ActiveConnection = Nothing ‘' 第 2 步

有關連接池的詳細信息,請參閱 ADO 和 SQL Server(英文)引用。

技巧 6:妙用 Session 對象

在肯定了在 Applications 和 Sessions 中緩存的優點之後,我們建議您避免使用 Session 對象。下面將會談到,當用於忙碌站點時,Sessions 有幾個缺點。所謂忙碌,通常是指站點每秒請求數百頁或同時有數千個用戶。該技巧對於必須進行水平擴展的站點,即那些利用多個服務器來適應負載或執行容錯功能的站點來說,更加重要。對於較小的站點,如 intranet 站點,Sessions 的便利,與開銷相比也是值得的。

為了翻新,ASP 自動為每個訪問 Web 服務器的用戶創建一個 Session。每個 Session 有大約 10 KB 內存開銷(在存儲在 Session 中的任何數據中是最高的),並使所有的請求都慢了一點。Session 一直保持活動狀態,直到達到可配置的超時(通常 20 分鐘)為止。

Session 最大的問題不是性能而是可伸縮性。Session 不能跨越 Web 服務器;一旦在一個服務器上創建了 Session,它的數據就保持在那裡。這意味著,如果您在 Web 領域中使用 Sessions,您將不得不為每個用戶的請求設計一種策略,以便始終將這些請求引向用戶的 Session 所在的服務器。這被稱為將用戶"粘"到 Web 服務器上。術語"粘性會話"即來源於此。由於 Session 沒有保持到磁盤上,所以,當 Web 服務器崩潰時,被"粘住"的用戶將丟失他們的 Sessions 狀態。

用於實施粘性會話的策略包括硬件和軟件解決方案。如 Windows 2000 Advanced Server 中的網絡負載平衡解決方案和 Cisco 公司的"本地指向器"解決方案可以實施粘性會話,但以犧牲一些可伸縮性為代價。這些解決方案並不完美。我們不主張您現在全盤推翻您的軟件解決方案(我們過去常用 ISAPI 篩選器和 URL 矯直對方案進行檢查)。

Application 對象也不能跨越服務器;如果您需要在 Web 領域內共享並更新 Application 數據,則需要使用後端數據庫。但只讀的 Application 數據在 Web 領域中仍然有用。

如果只是為了增加正常運行時間(用於處理故障轉移和服務器維護),大多數執行重要任務的站點將需要部署至少兩台 Web 服務器。所以,在設計執行重要任務的應用程序時,您將需要實施"粘性會話",或者簡單地避開 Sessions 以及其他任何在單個 Web 服務器上存儲用戶狀態的狀態管理技術。

如果當前沒有使用 Sessions,請確保將它們關閉。可以通過"Internet 服務管理器"(請參閱 ISM 文檔)來為應用程序執行該操作。如果決定使用 Sessions,可以采取幾個方法來將對性能的影響降低到最小。

可以將不需要 Sessions 的內容(如"幫助"屏幕、訪問者區域等)移動到關閉了 Sessions 的、單獨的 ASP 應用程序中。可以逐頁提示 ASP:在給定的頁中您不需要 Session 對象;使用位於 ASP 頁頂端的如下指令:

<% @EnableSessionState=False %>

使用該指令的一個很好的原因是,Session 給框架集帶來了有趣的問題。ASP 保證任何時候只執行一個來自 Session 的請求。這樣可以確保如果浏覽器為一個用戶請求了多個頁時,在每一時刻只有一個 ASP 請求將進入 Session;這就避免了在訪問 Session 對象時出現多線程問題。遺憾的是,結果,框架集中的所有頁均被以串行化方式繪制,一個接一個地,而不是同時地。這樣,用戶可能不得不等待很長時間才能得到所有框架內容。這意味著:如果某些框架頁不信任 Session,一定要使用
@EnableSessionState=False
指令告訴 ASP。

作為使用 Session 對象的替代方式,有很多方法可以用來管理 Session 狀態。對於狀態數量較小的情況(不到 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 對象代碼怎樣合並才能產生最佳性能還有待測試。注意,與 Windows NT(R) 4.0/IIS 4.0 相比,Microsoft 已經在 Windows 2000/IIS 5.0 中極大地提高了腳本和 ADO 性能。這樣,已編譯代碼對 ASP 代碼的性能優勢已經隨著 IIS 5.0 的引入而降低。

有關在 ASP 中使用 COM 對象的優缺點的更多討論,請參閱 ASP 組件准則和用 COM 和 Microsoft Visual Basic 6.0 對分布式應用程序進行編程(英文)。如果您的確部署了 COM 組件,要對它們進行強度測試是非常重要的。實際上,所有 ASP 應用程序都應當作為正式過程進行強度測試。

技巧 8:晚點獲取資源,早點釋放資源

這是個小技巧。通常,最好晚點獲取資源而要早點釋放資源。這些資源包括 COM 對象、文件句柄和其他資源。

ADO 連接和記錄集是這種優化的首要目標。當您使用完記錄集,就是說用它的數據打印完一個表格後,請立即將它釋放,而不是等到頁的末尾。將您的 VBScript 變量設置為
Nothing
是最好的做法。不要讓記錄集簡單地脫離作用域。同時,應當釋放任何有關的 Command 或 Connection 對象。(不要忘了對記錄集或"連接"調用
Close()
,在將它們設置為
= Nothing
之前。)這將縮短數據庫必須為您調整資源的時間跨度,並將數據庫連接盡可能快地釋放給連接池。

技巧 9:進程外的執行將犧牲可靠性

ASP 和 MTS/COM+ 都有允許您以可靠性換取性能的配置選項。當建立和部署應用程序時,應當理解這種交換。

ASP 選項

ASP 應用程序可以配置為以三種方式之一運行。在 IIS 5.0 中引入了術語"隔離級"來描述這些選項。三個隔離級值分別是低、中和高:

低級隔離。該隔離級在所有版本的 IIS 中受到支持,並且是最快的。它在主 IIS 進程 Inetinfo.exe 中執行 ASP。如果 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 選項

COM 組件也有三個配置選項,雖然與 ASP 選項不完全相似。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:顯式使用選項

在 .asp 文件中顯式使用
選項 Explicit
。置於 .asp 文件開頭的這一指令,強制開發人員聲明所有要使用的變量。許多開發人員認為這有助於調試應用程序,因為它避免了錯誤鍵入變量名稱而不經意地新建變量(例如,
MyXLMString=...
而非
MyXMLString=)

也許更重要的是,聲明的變量比未聲明的變量快。實際上,腳本運行時,在每次使用未聲明變量時按照名稱引用。而聲明的變量,在編譯或運行時分配了序號。這樣,聲明的變量按照該序號引用。由於
選項 Explicit
強制變量聲明,因此保證聲明了所有變量而實現快速訪問。

技巧 11:在子例程和函數中使用局部變量

局部變量是在子例程和函數中聲明的變量。在子例程和函數中,局部變量訪問要快於全局變量訪問。使用局部變量還可以使代碼更加清晰,因此盡可能使用局部變量。

技巧 12:將常用數據復制到腳本變量

在 ASP 中訪問 COM 時,應該將常用的對象數據復制到腳本變量中。這將削減 COM 方法的調用,COM 方法的調用與訪問腳本變量相比,要相對昂貴些。在訪問 Collection 和 Dictionary 對象時,這一技術也可以削減了昂貴的查找。

通常,如果打算多次訪問對象數據,請將數據放入腳本變量。該優化的主要目標是 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 ‘' 對 blah 做一次解析
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
數組。從關心性能的角度來說,如果計算機受物理內存的限制,最好一開始將數組的維數設置為最差方案 - 而不要將維數設置為最佳方案,再根據需要重新定義維數。這並不意味著明知道不需要那麼多而就是應該分配太多的內存。

下面代碼展示了您沒有必要地使用了
Dim

Redim
來解決。

<%
Dim MyArray()
Redim MyArray(2)
MyArray(0) = "hello"
MyArray(1) = "good-bye"
MyArray(2) = "farewell"
...
‘' 一些別的代碼中,這裡您不需要更多的空間,然後 ...
Redim Preserve MyArray(5)
MyArray(3) = "more stuff"
MyArray(4) = "even more stuff"
MyArray(5) = "yet more stuff"
%>

更好的辦法是只須一開始
Dim
數組為正確的大小(本例中為 5),而不是
Redim
數組,再加大數組。這可能會浪費一點兒內存(如果沒有用盡所有元素),但是獲得的是速度。

技巧 14:使用響應緩沖

您可以通過打開"響應緩沖區"來緩沖值得輸出的整個頁。這將寫入浏覽器的數據量降為最小,從而提高總體性能。每次寫入都會有大量開銷(包括 IIS 和通過電纜發送的數據量),因此寫入的越少越好。TCP/IP 的工作效率,在發送少量大的數據塊時明顯高於發送大量小的數據塊時,原因在於它的低速啟動和 Nagling 算法(用於最小化網絡阻塞)。

打開響應緩沖有兩種方法。第一種,可以使用"Internet 服務管理器"為整個應用程序打開響應緩沖。這是推薦的方法,在 IIS 4.0 和 IIS 5.0 中,在默認情況下,為新的 ASP 應用程序打開響應緩沖。第二種,逐頁將下列代碼行放在 ASP 頁的開頭,從而啟用響應緩沖:

<% Response.Buffer = True %>

該行代碼必須在任何響應數據寫入浏覽器之前執行(也就是說,在任何 HTML 出現在 ASP 腳本中之前和任何 Cookies 被使用
Response.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:批處理內嵌腳本和 Response.Write 語句

VBScript 語法
<% = expression %>
將"
表達式
"的值寫入 ASP 輸出流。如果響應緩沖沒有打開,則這些語句的每一句都會導致通過網絡,以許多小型包的形式,向浏覽器寫入數據。這是非常慢的。另外,解釋少量腳本和 HTML,將導致在腳本引擎和 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 頁。如果他們單擊了 Refresh 或跳轉到服務器的其他頁上,在 ASP 請求隊列的末尾將有一個新的請求,而在隊列的中間有一個斷開連接的請求。這通常發生在服務器處於高負荷的情況下(它有一個很長的請求隊列,相應的響應時間也很長),這只能使情況更糟。如果用戶不再連接,將沒有執行 ASP 頁的點(特別是低速、重量級的 ASP 頁)。可以使用
Response.IsClientConnected
屬性檢查這種情況。如果它返回
False
,則應調用
Response.End
並放棄該頁的剩余內容。實際上,每當 ASP 要執行新的請求時,IIS 5.0 便將該方法編碼,來檢查隊列中的請求有多長。如果在那裡超過了 3 秒鐘,ASP 會檢查客戶是否仍然連接著,如果客戶已斷開連接,就立即結束該請求。您可以使用 metabase 中的
AspQueueConnectionTestTime
設置,調整這 3 秒的超時時間。

如果有某頁執行了很長時間,您可能還想按一定的時間間隔檢查
Response.IsClientConnected
。在啟用響應緩沖之後,按一定的時間間隔執行
Response.Flush
,告訴用戶正在進行的是哪些事情,是個好辦法。

注意 在 IIS 4.0 中,
Response.IsClientConnected
將不能正常工作,除非首先執行
Response.Write
。如果啟用了緩沖,也需要執行
Response.Flush
。在 IIS 5.0 中則不必如此 -
Response.IsClientConnected
工作得很好。在任何情況下,
Response.IsClientConnected
都要有些開銷,所以,只有在執行至少要用 500 毫秒(如果想維持每秒幾十頁的吞吐量,這是一個很長的時間了)的操作前才使用它。作為通常的規則,不要在緊密循環的每次迭代中調用它,例如當繪制表中的行,可能每 20 行或每 50 行調用一次。

技巧 17:使用 <OBJECT> 標記實例化對象

如果需要引用不能在所有代碼路徑中使用的對象(尤其是服務器 - 或應用程序 - 作用域的對象),則使用 Global.asa 中的
<object runat=server id=objname>
標記來聲明它們,而不是使用
Server.createObject
方法。
Server.createObject
立刻創建對象。如果以後不使用那個對象,就不要浪費資源。
<object id=objname>
標記聲明了 objname,但實際上 objname 此時並沒有創建,直到它的方法或屬性第一次被使用時才創建。

這是遲緩計算的另一個例子。

技巧 18:使用 ADO 對象和其他組件的 TypeLib 聲明

當使用 ADO 時,開發人員經常包含
adovbs.txt
來獲得對 ADO 不同常量的訪問權。該文件必須包含在要使用這些常量的每一頁中。該常量文件非常大,給每個 ASP 頁增加了很多編譯時間和腳本大小方面的開銷。

IIS 5.0 提供了綁定到組件類型庫的能力。允許您在每個 ASP 頁上引用一次類型庫並使用它。每頁不需要為編譯常量文件付出代價,並且組件開發人員不必為在 ASP 中的使用而生成 VBScript #include 文件。

要訪問 ADO 類型庫,請將下列語句之一放入 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" -->

技巧 19:利用浏覽器的驗證能力

流行的浏覽器具有對以下功能的高級支持,例如 XML、DHTML、Java 小程序以及遠程數據服務。請盡量利用這些功能。所有這些技術,都可以通過執行客戶端的驗證和數據緩存,減少了與 Web 服務器之間的往返。如果您正在運行智能浏覽器,該浏覽器可以為您進行一些驗證(例如,在運行 POST 之前檢查信用卡的校驗和否有效)。重申一次,請盡量使用這些功能。由於削減了客戶端到服務器的往返路程,將減少對 Web 服務器的壓力,並且削減了網絡通信量(雖然發送給浏覽器的初始頁面可能更大),服務器訪問的所有後端資源也削減了。而且用戶不必經常提取新頁,使用戶的感受好一些。這並不減輕對服務器端驗證的需要。還是應該經常進行服務器端的驗證。這樣能夠防止由於某些原因從客戶端來的壞數據,例如黑客,或者不運行客戶端驗證程序的浏覽器。

許多站點由獨立於浏覽器創建的 HTML 組成。這一點經常阻礙開發人員利用可以提高性能的流行浏覽器功能。對於真正高性能的、必須關心浏覽器的站點,良好的策略是針對流行的浏覽器優化您的頁面。在 ASP 中使用"浏覽器性能組件",很容易檢測到浏覽器的功能。諸如 Microsoft FrontPage 等工具,能幫助您設計使用所希望的目標浏覽器和 HTML 版本的代碼。更詳細的討論,請查看 When is Better Worse? Weighing the Technology Trade-Offs(英文)。

技巧 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"


。在第三次迭代中,它必須再次重新分配

,並復制三個字符到

。在第 N 次(26 次)迭代中,它必須重新分配並復制 N 個字符到

。就是 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 += "某字符串",
而不是
s = s + "某字符串"

技巧 21:啟用浏覽器和代理緩存

默認情況下,ASP 禁用浏覽器和代理中的緩存。這將很有意義,因為 ASP 生來就是動態的,具有潛在地對時間敏感的信息。如果有一個不需要對每次查看進行刷新的頁,則應該啟用浏覽器和代理緩存。這使得浏覽器和代理能在某一段時間內,使用某一頁的緩存副本,這時間的長短可以控制。緩存能明顯減輕服務器負荷,使用戶的感受好一些。

哪種動態頁可以緩存?舉例說明:

天氣頁,每 5 分鐘更新一次。
列出新聞的主頁或新聞發布的主頁,每天更新 2 次。
公共基金運營列表,基本的統計數小時更新 1 次。
請注意,使用浏覽器或代理緩存,只有很少的命中被記錄到 Web 服務器上。如果想精確測量所有頁面查看或者張貼廣告,也許不喜歡使用浏覽器和代理緩存。

浏覽器緩存是由 Web 服務器發往浏覽器的 HTTP 截至期限標題控制的。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> 內部。一些浏覽器會響應這條指令,但代理不會。

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

最後,可以標識內容對 HTTP 代理緩存是否有效,請使用
Response.CacheControl
屬性。設置屬性為"Public",允許代理緩存內容。

<% Response.CacheControl = "Public" %>

默認情況下,該屬性設置為"Private"。注意,不應當為顯示某用戶專用數據的頁啟用代理緩存,因為代理也許為屬於其他用戶的用戶頁面服務。

技巧 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("Data") )。對於不在 Request.Cookies 、 Request.Form 、 Request.QueryString 或 Request.ClientCertificate 中的項,有對 Request.ServerVariables 的隱含調用。
Request.ServerVariables
集合比其他集合慢很多。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved