ASP完美優化(不斷更新)

 經過本人將ASP運行速度內存佔用大小放大到200M的測試

    關於定義變量:

1、定義變量,儘量不要定義全局變量,私有變量在運行速度以及空間佔用上面比公共變量速度快,以及賦值上面速度問題(下面介紹)

2、變量賦值:

    給變量賦值儘量一次賦完,比如:

應該修改爲:

解釋:在運行速度上,很明白的看出來第二個比第一個快,但是在內存佔用上呢?經過本人在將變量放大到200M之後發現,變量第二次累加值,佔用內存以及運行速度是第一次的三倍以上,也就是說,你把一個字符串拆分的越多,運行速度以及內存佔用將大大增加。

    變量需要重複賦值問題比如:

應該修改爲:

解釋:這個一般人都會按照第一個方法寫,第一簡單;第二代碼行數少看起來清析點。在本人200M變量大小賦值之後發現,變量第一次賦值後,如果不手動釋放內存,內存不會自動清空,變量內存佔用空間會累加上去,所以同步解釋上面爲什麼要把變量一次賦完的速度將快很多。同樣注意,這個問題在公共變量以及變量佔用內存大的時候要儘早的釋放將會增加速度,以及內存消耗。

這裏說明一下""、Empty、Null、vbNullString、Nothing差別,他們在內存消耗上面沒法放大,所以在我測試時間,他們內存消耗沒法測到,但是都差不多,用哪個都行,他們之間到底有什麼差別,在我另外一篇博客關於Null、Empty、vbNullString、Nothing差別裏面談到。

3、關於使用函數以及子過程

 以下代碼

應該修改爲:

解釋:使用函數返回字符,儘量不要使用變量,如果非得要用變量,儘量使用私有變量,因爲Function,Sub私有變量,會在執行完Function,Sub時候自動清除內存。如果在函數內非得使用公共變量,那麼要先把公共變量賦值,然後給Function賦值,因爲先給Function賦值,再給公共變量賦值,系統會把Function使用的內存空間累加到公共變量上,所以儘量不要先給函數賦值。下面解釋一下很多疑問:

另外解釋一下,Function,Sub私有變量在Function,Sub運行完時候,會自動立即消除內存,可以不用擔心內存累加。

4、如果一個對象要用好多次,創建一次,馬上關閉,等到下次再用再次創建,這樣速度明顯變慢,在測試創建1024*1024個FSO時間,創建這麼多的FSO,最後關閉,與測試創建1024*1024個FSO,最後不關閉,與測試創建FSO對象然後立馬關閉1024*1024次,對比發現,FSO每創建一次,關閉一次,速度比創建N次最後關閉慢太多了(測試中每創建一次關閉一次,Server.Time時間不夠,我Server.Time爲默認),在此糾正所有人一個錯誤,所有人認爲,如果不手動關閉FSO那麼,此FSO會一直存在佔用內存,經過不關閉FSO創建1024*1024次最後運行完畢測試,FSO在運行完時自動關閉。我用的是IIS5。

相關代碼及說明:

(有一個問題有點矛盾,速度自然是創建一次,最後釋放,對於多次使用的對象來說是速度快的,但是對於多用戶,這樣的消耗內存可能會減少同時在線用戶數量)

 

 

 

下面是送別的網上找過來的,相對比較全的優化方法:

1將經常使用的數據緩存在 Web 服務器上
   典型的 ASP 頁從後端數據存儲中檢索數據,然後將結果轉換成超文本標記語言 (HTML)。無論數據庫的速度如何,從內存中檢索數據總要比從後端數據存儲中檢索數據快得多。從本地硬盤讀取數據通常也比從數據庫中檢索數據更快。因此,通常可以將數據緩存在 Web 服務器上(存儲在內存或磁盤中),來提高性能。 緩存是傳統的以空間換取時間的做法。如果您緩存的內容正確,那麼您可以看到性能會有顯著的提高。爲使緩存有效,必須保存那些經常重複使用的數據,且要重新計算這些數據需要(適度)大的開銷。如果緩存的都是些陳舊的數據,就會造成內存浪費。 不經常發生改變的數據是很好的緩存候選數據,因爲您不必擔心隨着時間的遷移該數據與數據庫同步的問題。組合框列表、引用表、DHTML 碎片、擴展標記語言 (XML) 字符串、菜單項和站點配置變量(包括數據源名稱 (DSN)、Internet 協議 (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 頁中添加一些代碼(或編寫一個可重複使用的腳本函數),以檢查數據是否存在,如果不存在,就裝載數據。這是一個傳統的性能技術,稱爲“惰性計算” - 在您知道需要某一個值以前不計算該值。例如: 可以爲所需要的每個數據塊編寫類似的函數。 應以什麼格式存儲數據?可以存儲任何變體類型,因爲所有腳本變量都是變體型。例如,您可以存儲字符串、整數或數組。通常,您將以這些變量類型之一存儲 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 = "" & 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 & " " & fldName & "" & vbCrLf rs.MoveNext Loop s = s & "" & 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 頁來更新數據。或者,您可以通過函數定期自動刷新數據。下面例子存儲帶有緩存數據的時間戳,並隔一段時間後刷新數據。 Session[/b] 或 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® XML 解析器 (MSXML) 支持保存和裝載 XML 文檔。
   LookupTable 對象(例如,用在 MSN 上)是從磁盤裝載簡單列表的最好選擇。
 最後,應考慮將數據的表示緩存在磁盤上,而不是數據本身。預先轉換的 HTML 可以用 .htm 或 .asp 文件存儲在磁盤上,超級鏈接可以直接指向這些文件。可以使用商用工具,如 XBuilder,或 Microsoft® 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® 2000 和 COM+ 的新增模型。) 下列組件不是敏捷的:

   ○自由線程的組件(除非它們聚集 FTM)。
   ○單元線程組件。
   ○單線程組件。

   配置的組件(Microsoft Transaction Server (MTS)/COM+ 庫和服務器程序包/應用程序)不是敏捷的,除非它們是 Neutral 線程。單元線程組件和其它非敏捷的組件在頁作用域內是最適合的(即,它們在單個 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 中使用 避免這一錯誤,但不建議這樣做,因爲這會導致彙集和串行化,關於這一點將在下面講述。 如果您緩存非敏捷的組件會出現什麼毛病?緩存在 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不要將數據庫連接緩存在 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 ' step 1' Populate the recordset with datars.Open strQuery, strProv' Now disconnect the recordset from the data provider and data sourcers.ActiveConnection = Nothing ' step 2有關連接池的更詳細信息,可以在 ADO 和 SQL Server 參考資料中找到。
6合理地使用 Session 對象
   既然我們已經討論了緩存在 Application 和 Session 中的優點,現在開始討論避免使用 Session 對象的問題。正如下面所討論的,當與忙的站點一起使用時,Session 有幾個缺點。“忙”的意思一般是指一秒鐘要求幾百頁面或成千上萬同時用戶的站點。這個技巧對於必須水平擴展的站點 - 即,那些利用多臺服務器以處理負載或實現容錯的站點 - 甚至更重要。對於較小的站點,諸如 Intranet 站點,要想實現 Session 帶來的方,必然增大系統開銷。 簡言之,ASP 自動爲每個訪問 Web 服務器的用戶創建一個 Session。每個 Session 大約需要 10 KB 的內存開銷(最主要的是數據存儲在 Session 中),這就使所有的請求都減慢。在配置的超時時段(通常是 20 分鐘)結束以前,Session 一直保留有效。 Session 的最大的問題不是性能,而是可擴展性。Session 不能跨越幾臺 Web 服務器,一旦在一臺服務器上創建 Session,其數據就留在那兒。這就意味着如果您在一個 Web 服務器羣使用 Session,您必須設計一個策略,將每個用戶請求始終發到用戶 Session 所在的那臺服務器上。這被稱爲將用戶“粘”在 Web 服務器上。術語“粘性會話”就是從這裏派生而來的。如果 Web 服務器崩潰,被“粘住的”用戶將丟失他們的會話狀態,因爲會話不是粘到磁盤上。 實現粘性會話的策略包括硬件和軟件解決方案。諸如 Windows 2000 Advanced Server 中的網絡負載平衡和 Cisco 的 Local Director 之類的解決方案都可以實現粘性會話,代價是要損失一定程度的可擴展性。這些解決方案是不完善的。不建議此時部署您自己的軟件解決方案(我們過去常常使用 ISAPI 篩選器和 URL 轉換等等)。 Application 對象也不跨越多臺服務器,如果您必須跨越 Web 服務器羣共享和更新 Application 數據,您必須使用後端數據庫。但是,只讀 Application 數據在 Web 服務器羣中仍是有用的。 如果只是因爲要增加運行時間(處理故障轉移和服務器維護),大多數關鍵任務站點至少需部署兩臺 Web 服務器。因此,在設計關鍵任務應用程序時,必須實現“粘性會話”,或乾脆避免使用 Session,以及任何其它將用戶狀態存儲在單個 Web 服務器上的狀態管理技術。 如果您不使用 Session,一定要將它們關閉。您可以通過 Internet Services Manager,爲應用程序執行此操作(參見 ISM 文檔)。如果您決定使用 Session,您可以採用一些方法減輕它們對性能的影響。 您可以將不需要 Session 的內容(如幫助屏幕,訪問者區域等等)移到另一個關閉了 Session 的 ASP 應用程序中。您可以逐頁提示 ASP,您不再需要該頁面上的 Session 對象,使用以下放在 ASP 頁面最上面的指令: 使用這一指令有一個很好的理由是,這些 Session 在框架集方面存在一個有意思的問題。ASP 保證任何時候 Session 只有一個請求執行。這樣就確保如果瀏覽器爲一個用戶請求多個頁面,一次只有一個 ASP 請求接觸 Session,這樣就避免了當訪問 Session 對象時發生的多線程問題。很遺憾,一個框架集中的所有頁面將以串行方式顯示,一個接一個,而不是同時顯示。用戶可能必須等候很長時間,才能看到所有的框架。該故事的寓意:如果某些框架集頁面不依靠 Session,一定要使用 @EnableSessionState=False 指令告訴 ASP。 有許多管理 Session 狀態的方法,可替代 Session 對象的使用。對於少量的狀態(少於 4 KB),我們通常建議使用 Cookies、QueryString 變量和隱式變量。對於更大數據量,如購物小車,後端數據庫是最適合的選擇。有關 Web 服務器羣中狀態管理技術的文章很多。有關詳細信息,請參見 Session 狀態參考資料。
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 NT® 4.0/IIS 4.0 相比,Windows 2000/IIS 5.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 是最好的做法。不要讓記錄集超出作用域之外。而且,要釋放任何相關的 Command 或 Connection 對象(在將記錄集或連接設置爲 = Nothing 之前,不要忘記調用 Close())。這會縮短數據庫必須爲您準備資源的時間,並儘快釋放數據庫到連接池的連接。
9進程外執行過程以性能換取可靠性
   ASP 和 MTS/COM+ 兩者都有配置選項,可使您兼顧可靠性和性能。當建立和部署應用程序時,應知道如何兼顧兩者的性能。
10:使用顯式選項
   在 .asp 文件中應使用 Option Explicit。此指令放在 .asp 文件的最上面,它強制開發人員聲明要使用到的所有變量。許多程序員認爲這種方法對於調試應用程序很有幫助,因爲這種方法避免了鍵錯變量名和誤建新變量的可能性(例如,將 MyXMLString=) 錯寫成 MyXLMString=...。
   更重要的一點也許是,聲明的變量比未聲明的變量速度更快。由此,腳本在運行時每次用到未聲明的變量時,按名稱引用它。另一方面,聲明的變量是有順序的,要麼以編譯時間,要麼以運行時間。以後,聲明的變量都按此順序引用。因爲 Option 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 ' ...

 當此代碼運行時,下面是發生的情況:
   1、變量 Foo 被解析爲全局對象。
   2、變量 bar 被解析爲 Foo 的成員。這實際就是一次 COM 方法調用。
   3、變量 blah 被解析爲 Foo.bar 的成員。這又是一次 COM 方法調用。
   4、變量 qaz 被解析爲 foo.bar.blah 的成員。沒有錯,這還是一次 COM 方法調用。
   5、調用 Foo.bar.blah.quaz(1)。再一次 COM 方法調用。懂了嗎?
   6、再次執行步驟 1 至步驟 3 以解析 baz。系統並不知道調用 qaz 是否改變對象模型,因7、此必須再次執行步驟 1 至 3 以解析 baz。
   8、將 baz 解析爲 Foo.bar.blah 的成員。賦予屬性。
   9、再次執行步驟 1 至步驟 3 以解析 zaq。
   10、再次執行步驟 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 數組。就性能而言,如果計算機的物理內存大小有限,最好將數組的初始維數設置爲其最不利的情況 - 或將維數設置爲其最佳的情況,然後再按需要重新確定維數。這並非意味着,如果知道您不需要內存時,就隨便分配幾兆字節的內存。
 下面的代碼給您顯示使用 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:批處理內嵌腳本和 Response.Write 語句
   VBScript 語法 <% = expression %> 將“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 頁面。如果他們單擊刷新或移到服務器上的另一個頁面,在 ASP 請求隊列的末尾就有一個新的請求等候,在隊列的中間有一個斷開連接的請求。當服務器的負載很高時(因此請求隊列就會很長,響應時間也會相應地變長),就會經常發生這種情況,這樣只能使情況變得更糟。如果用戶不再連接,執行 ASP 頁面(特別是慢的、大的 ASP 頁面)已沒有任何意義。您可以使用 Response.IsClientConnected 屬性檢查這一情況。如果它返回 False,則應調用 Response.End 並放棄頁的其餘部分。事實上,IIS 5.0 已將這一做法編爲程序 - 每當 ASP 即將執行新請求時,它就會檢查請求在隊列中已等候了多長時間。如果已經在那裏等候了多於 3 秒鐘,ASP 將檢查客戶機是否仍處於連接狀態,如果沒有連接,就立即終止請求。您可以在配置數據庫中使用 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:對於ADO和其它組件使用TypeLib聲明
   當使用 ADO 時,開發人員經常加入 adovbs.txt,以訪問 ADO 的各種常量。在要使用常量的每個頁面中必須包含此文件。此常量文件相當大,給每個 ASP 頁面的編譯時間和腳本大小增加了許多系統開銷。
   IIS 5.0 引入了綁定到組件類型庫的功能。這可使您引用類型庫一次,並將其用在每個 ASP 頁面上。每個頁面不會產生編譯常量文件的開銷,且組件開發人員不必建立 VBScript#_include 文件以在 ASP 上使用。
   要訪問 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" -->
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") 複製到 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 += "某字符串",而不使用 s = s + "某字符串"。
21:啓用瀏覽器和代理緩存
   在默認情況下,ASP 禁止在瀏覽器和代理中進行緩存。這是有意義的,因爲就實質而言 ASP 頁面是動態的,上面有隨時間不斷變化的潛在信息。如果頁面不要求在每個視圖上進行刷新,您應啓用瀏覽器和代理緩存。這可使瀏覽器和代理在一定的時間內使用頁面的“緩存”副本,您可以控制時間的長短。緩存可以大大減輕服務器上的負載,縮短用戶的等待時間。
   哪一種動態頁面可作爲要緩存的頁面呢?下面舉一些例子:
   天氣預報頁面,在此頁面上,每隔 5 分鐘更新一次天氣預報。
   列出新聞條目或新聞稿的主頁,它一天更新兩次。
   共同基金業績列表,在此列表中,基本統計信息每隔幾小時更新一次。

   注意,在使用瀏覽器或代理緩存的情況下,Web 服務器上記錄的訪問次數減少了。如果您想準確地測量所有頁面視圖或張帖公佈,您就不希望使用瀏覽器和代理緩存。
 瀏覽器緩存由 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> 部分。一些瀏覽器將遵照此指令,而代理則不然。
 <META HTTP-EQUIV="Expires" VALUE="May 31,2001 13:30:15">

   最後,您可以使用 Response.CacheControl 屬性,指示其內容是否可以讓 HTTP 代理緩存。若將此屬性設置爲“Public”,代理就可以緩存此內容。
 <% Response.CacheControl = "Public" %>

   在默認情況下,此屬性被設置爲“Private”。注意,對於顯示某用戶特定數據的頁面,不應啓用代理緩存,因爲代理可能給用戶提供屬於其他用戶的頁面。
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 集合比其它集合慢得多。
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,我們常常發現,增加 ASP ProcessorThreadMax 參數(參見 IIS 文檔)可以顯著改善性能,特別是在傾向於等待後端資源(如數據庫)或其它中間產品(如屏幕刷)的站點上。在 IIS 5.0 中,您可能發現啓用 ASP Thread Gating 比查找一個 AspProcessorThreadMax 最佳設置效率更高。

27:優化轉向鏈接

       在任何可能時使用Server.Transfer,而不要用Response.Redirect
   Response.Redirect告訴瀏覽器請求另一個不同的頁面,這常常用於引導用戶到登錄頁面或者出錯處理頁面。由於重定向強迫了一個新頁面請求,結果是瀏覽器必須要與Web服務器循環2次,並且Web服務器必須處理一個額外的請求。IIS5.0引進了一個新功能Server.Transfer,它執行在同一服務器上的頁面傳輸,這將避免額外的瀏覽器-Web服務器的數據循環,形成良好的系統性能,對於用戶也有較好的響應時間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章