ASP 能快速執行你的動态網頁,但你還可以通過緊縮代碼和數據庫連接以使它們執行更快。這是一(yī)篇關于怎樣精簡代碼和Asp 特征以獲得最快執行速度的詳細文章。對于一(yī)個急燥的用戶來說,任何在按下(xià)用戶按鈕到結果出現在它們的屏幕之間的延遲可能意味着它們會轉到浏覽其它的站點? 假如你的是商(shāng)業站點,這有可能意味着失去(qù)潛在的銷售。
我(wǒ)們沒有任何辦法控制用戶的帶寬,但我(wǒ)們的确能通過優化Asp 站點來獲得最佳的性能。大(dà)部分(fēn)潛在性能的提升是通過系統改變而不是緊縮代碼,一(yī)個不合适的想法是,一(yī)旦遇到系統效率問題,就向系統管理者提意見要其升級系統。
首先,哪個因素可能影響Asp的性能?很不幸,有很多因素?下(xià)面這些隻是其中(zhōng)的一(yī)部分(fēn):
可用帶寬
服務器上的處理器和其它硬件的速度
在服務器上運行的其它程序(比如象那些OpenGL屏幕保護程序!)
數據庫連接模式,連接池,數據庫系統本身(比如Oracle優于Sql Server,Sql server優于Access)
所使用的語言
存儲過程優于行式Sql語句
使用編譯組件而不是VB或JavaScript,好的Asp編程經驗,比如錯誤處理等
一(yī)些以上的因素可能已經被有IIS 知(zhī)識經驗的開(kāi)發者普遍留意到了,但其它的可能對于他們來說是十分(fēn)複雜(zá)的問題。在這篇文章裏, 将試着解釋所有影響Asp性能的每個因素,讓我(wǒ)們看一(yī)看那些在我(wǒ)們刮胡子的幾毫秒内就能做到的主要事情。
ASP腳本大(dà)小(xiǎo)
你是腳本頁(還有其它頁面)是不是比必須的長度要長?這是一(yī)開(kāi)始執行就會降低Asp 性能的東西。ASP 腳本在用來獲取信息和格式化輸出的時候是十分(fēn)有用的,但腳本也是逐行解釋執行,所以你的腳本越長,執行它的時間也就越長。
如果你的腳本很龐大(dà),怎麽做才能減少腳本的長度呢?這裏有幾點建議:
你可以将它們轉換成服務器端組件,也就是說,做成VB動态鏈接庫DLL或者通過先進的Windows編程語言或适當的COM 接口語言将它轉換成未編譯組件?并且在服務器端注冊它們。有關的快速指南(nán)可以在
http://www.webdevelopersjournal.com/articles/activex_for_asp.html找到。對一(yī)個寫得好的ActiveX 組件進行編譯不但能大(dà)幅度提高性能,還可以保護你的軟件(腳本),尤其當你将你的Asp站點發布在第三方主機上的時候。
因爲腳本是逐行解釋執行的,所以剔除多餘的腳本或建立更高效率的腳本能夠改進性能。如果你在單個Asp 文件中(zhōng)有數百行的代碼,可能這樣做你能很好地劃分(fēn)使用者,買賣和數據服務。事實上,如果你這樣做,可能會找出一(yī)些冗餘的代碼:如果你需要輸出幾個表格,你可以編寫一(yī)個通用函數來輸出一(yī)個表格,隻是多次調用它。
在講述Asp 腳本的大(dà)小(xiǎo)問題的時候,不得不提及包含文件的大(dà)小(xiǎo)。當你使用一(yī)個包含文件的時候,整個包含文件被裝入,當包含文件被包含的時候,相當于在Asp 文件本身寫下(xià)那部分(fēn)代碼。因此,如果你在一(yī)個冗長的包含文件裏定義了很多通用的方法和定義,要明白(bái)到在你包含該文件的時候,不管你要不要用到裏面的每個方法和定義,它都是被整個裝入的。ASP 緩存全部的展開(kāi)代碼,這會降低查找效率在這種情況下(xià),包含文件必須被分(fēn)割成更小(xiǎo)的,模塊化的文件。也要明白(bái)到包含文件被服務器視爲單獨的頁面請求,使用太多的包含文件會影響下(xià)載時間。
以下(xià)是引用片段: 〈!-- #include file="Header.asp" --〉 〈!-- #include file="Footer.asp" --〉 〈SCRIPT language="vbscript" runat="server"〉 Sub Main() WriteHeader WriteBody WriteFooter End Sub Sub WriteBody() ... End Sub Main?"調用過程Main 〈/SCRIPT〉
假如你的腳本冗長的話(huà),請使用Response.IsClientConnected。這意味着在客戶端不再連接到服務器的時候,你的服務器CPU能避免循環等待。
以下(xià)是引用片段: 〈% "檢查客戶端是否仍在連接 If Not Response.IsClientConnected Then "仍然連接着,處理程序 Else "斷開(kāi) End If %〉
Interspersing ASP and HTML
每個人都這樣做?當我(wǒ)們輸出表格的時候,我(wǒ)們會在ASP 和HTML代碼間轉換,而這是一(yī)個不好的習慣。例如:
以下(xià)是引用片段: 〈HTML〉 〈BODY〉 〈% Set MyConn = Server.CreateObject("ADODB.Connection") MdbFilePath = Server.MapPath("sample.mdb") MyConn.Open "Driver={Microsoft Access Driver (*.mdb)}; DBQ=" & MdbFilePath & ";" SQL_query = "SELECT * FROM Friends" Set RS = MyConn.Execute(SQL_query) WHILE NOT RS.EOF %〉 〈LI〉〈%=RS("Name")%〉: 〈A HREF=""〉Homepage〈/A〉 〈% RS.MoveNext WEND %〉 〈/BODY〉 〈/HTML〉
另一(yī)個普遍的例子是使用IF語句的時候:
以下(xià)是引用片段: 〈% If Not Session("DBOpen") Then %〉 〈H1〉Database not connected〈/H1〉 〈% Else %〉 〈H1〉Database open〈/H1〉 〈% End If %〉
在這些情況下(xià),腳本性能能通過将服務器端腳本寫到一(yī)起來,而用Response.write産生(shēng)Html代碼來提高性能。比如:
以下(xià)是引用片段: 〈% If not Session ("DBOpen") Then Response.Write "〈H1〉Database not connected〈/H1〉" Else Response.Write "〈H1〉Database open〈/H1〉" End If %〉
在大(dà)的腳本和很多腳本的情況下(xià),你将能看到性能的提高。注意這裏盡量避免了使用〈%标記,這樣就能提高性能,ASP不需在執行腳本的時候計算字符的Ascii碼。
Session狀态
無庸置疑地,在Asp中(zhōng)能夠通過Session維持某個狀态的能力是十分(fēn)強大(dà)的特色。然而,它會影響你的性能。明顯地,你的站點的可伸縮性性變成了另一(yī)個問題,如果限制Session的使用的話(huà)。然而,session會爲每個用戶消耗服務器資(zī)源。
如果你不使用session 變量,或事實上你不必使用?使用隐藏表單域,在數據庫中(zhōng)保存數據,查詢字符串是不是其中(zhōng)的竅門?所以你應該禁止Session狀态。你可以使用下(xià)面的聲明禁止使用session:
@EnableSessionState = False
這樣,ASP将不再檢查session信息。
如果你不得不依賴于session狀态,應該避免在session對象中(zhōng)存放(fàng)大(dà)量的數據。IIS中(zhōng)的session在客戶端的HTTP cookie可用的時候就會保持,導緻被session占用的内存在session 終止或超時前一(yī)直被占用。這樣,如果很多用戶同時使用你的程序的時候,你的服務器資(zī)源可能會耗盡。
數據庫訪問
數據庫訪問是必須的麻煩?訪問數據庫将會激烈地減慢(màn)你的程序,但很顯然,如果沒有數據庫,很多站點将變得毫無價值可言。但通過存儲過程訪問數據庫來代替使用嵌入式Sql 語句,你可以提升潛在的性能。通過使用存儲過程和ActiveX Data Objects (ADO),它們亦同樣擁有良好的靈活性。盡可能從存儲過程來輸出數據。
确認你的數據庫具有索引,因爲這樣能直接提高你的程序的效率。同樣,盡量在你的數據庫服務器運行更新統計(Update Statistics) 以幫助追蹤你的數據分(fēn)發,這樣,你的數據庫就能夠基于這些信息來改造查詢執行。注意一(yī)些數據庫比如MS Access,是不是真正能在企業級程序中(zhōng)接受?SQL Sever 7.0或者Oracle是一(yī)個更好的賭注。
讓SQL象它被設計的那樣工(gōng)作,它能count(統計),連接(join),排序(sort)和group 數據。當你能夠寫出一(yī)個查詢語句來做這些東西的時候,就不要自己用其它語言來實現。
下(xià)面是一(yī)個統計所有列的最簡單的語法:
SELECT count(*) FROM publishers WHERE state="NY"
如果你統計一(yī)個指定的列,你必須使用group by語句來分(fēn)組該列,否則它不會工(gōng)作:
SELECT count(city),city FROM publishers GROUP BY city
分(fēn)類返回的數據:
SELECT * FROM TableName WHERE FieldName〉50 OR FieldName〈100 ORDER BY FieldName2, Field Name3
使用Odbc還是文件DSN連接數據庫?使用快速的OLEDB Provider技術連接你的數據庫而不是使用DSN連接。不再需要懇求你的ISP(或數據庫管理員(yuán)/網管)爲你建立一(yī)個系統DSN,當你移走Web文件的時候,亦不需要改變配置。
OLEDB 介于ODBC層和應用程序之間。在你的ASP 頁面中(zhōng),ADO介于ODEDB之上的“應用程序”。你的ADO調用首先被送到OLEDB,接着被送到ODBC層。然而,你可以直接連接到OLEDB 層,并且如果你這樣做的話(huà),你就能看到服務器端性能的提高。然而,怎樣直接連接到OLEDB?
如果你使用SQLServer 7,使用下(xià)面的連接代碼連接數據庫:
strConnString = "DSN="";DRIVER={SQL SERVER};" & _
"UID=myuid;PWD=mypwd;" & _
"DATABASE=MyDb;SERVER=MyServer;"
最重要的參數是DRIVER=部分(fēn)。如果你要繞過ODBC而使用通過使用OLEDB 連接SQL Server(這是更快的連接),請使用下(xià)面的語法:
strConnString ="Provider=SQLOLEDB.1;Password=mypassword;" & _
"Persist Security Info=True;User ID=myuid;" & _
"Initial Catalog=mydbname;" & _
"Data Source=myserver;Connect Timeout=15"
有什麽不對的地方嗎(ma)?
現在你可能會覺得有點奇怪:我(wǒ)們在這個新的連接方法中(zhōng)的要點是什麽呢?爲什麽不使用标準DSN-less/System DSN途徑?呵,根據Wrox 在他的著作《ADO 2.0 Programmer"s Reference》中(zhōng)測試的結果表明,如果你使用OLEDB連接和DSN或者DSN-less連接方法比較,你會發現有下(xià)面的改進:
性能對比:
SQL Access
OLEDBDSNOLEDBDSN
連接時間:18?82?連接時間:62?99
查詢1,000條記錄時間:29005400查詢1,000條記錄時間: 100950
注釋:這個結果在Wrox的《ADO 2.0 Programmer"s Reference》一(yī)書(shū)的第232和233頁可以查到。時間的單位是毫秒,查詢1,000記錄時間是通過服務器端遊标計算出來的(當使用客戶端遊标的時候,OLEDB與DSN記錄集的性能之間的差别不大(dà))。
ASP譯碼問題:
盡可能在客戶端确認用戶輸入來減少HTTP來回請求的數量。如果浏覽器有支持JavaScript或其它腳本的能力,使用它們的力量以釋放(fàng)更多的服務器資(zī)源。
下(xià)面的VBScript運行于客戶端浏覽器,在提交到你的服務器之前,用來驗證用戶信息:
以下(xià)是引用片段: 〈SCRIPT LANGUAGE="VBScript"〉 〈!-- Sub btnEnter_OnClick Dim TheForm Set TheForm = Document.MyForm If IsNumeric(TheForm.Age.Value) Then TheForm.submit Else Msgbox "Please enter a numerical age." End if End Sub //--〉 〈/SCRIPT〉 〈FORMmethod="POST" name=MyFormaction="myfile.asp"〉? Name: 〈INPUT typr="text" name="Name"〉 Age: 〈INPUT type="text" name="Age"〉 〈INPUT type="button" name="btnEnter"value="Enter"〉 〈/FORM〉
使用局部變量,避免使用全局變量。局部變量比全局變量更快地被Asp 腳本引擎存取,因爲不需搜索整個名稱域。避免改變數組定義。在第一(yī)次初始化的時候就簡單分(fēn)配足夠的大(dà)小(xiǎo)效率更高。在這種情況下(xià),你可能會浪費(fèi)一(yī)些内存,但你獲得了速度的優勢。在服務器負載重的時候這個技術是顯然易見有效的。
如果你需要引用不一(yī)定要用到的對象,那麽最好使用〈OBJECT〉标記而不是用 Server.CreateObject方法。使用Server.CreateObject引起對象立即被建立,反之,〈OBJECT〉标記則不會這樣立即建立對象如果使用〈object〉定義後不使用該對象,你不會浪費(fèi)資(zī)源。
例如:下(xià)面的例子是一(yī)個使用〈OBJECT〉标記建立一(yī)個application-scope廣告輪 Ad Rotator對象實
例:
以下(xià)是引用片段: 〈OBJECT runat=server scope=Application id=MyAds progid="MSWC.AdRotator"〉 〈/OBJECT〉
在存儲該Ad Rotator對象進Application後,你可以在任何程序的頁面中(zhōng)用下(xià)面的語法訪問該對象
〈%=MyAds.GetAdvertisement("CustomerAds.txt") %〉
打開(kāi)"Option Explicit"開(kāi)關。在VB和VBScript 中(zhōng),你可以在沒有顯式聲明的情況下(xià)使用變量。但打開(kāi)這個選項可以鑒别用定義變量,這樣可以很好地書(shū)寫變量,并能幫助提高性能。未定義的局部變量會變慢(màn),因爲在建立它之前,名稱空間必須被搜遍後才知(zhī)道變量是否存在。擺脫它,使每個變量清楚地定義(先定義後使用)。
這是一(yī)個好習慣,it may trap typos, 這樣更快。
除非你真正需要使用,否而不要使用Server.MapPath方法。如果你知(zhī)道真實路徑就使用真實路徑。使用MapPath需要IIS找回現時服務器路徑,這意味着得向服務器發一(yī)個特殊的請求,也就意味着降低了性能。另一(yī)個方法是将路徑存放(fàng)到局部變量中(zhōng),在需要的時候使用,這樣就不需要服務器多次查找。
檢查你自己是怎麽做的
你可以通過工(gōng)具來測量你的系統性能,比如系統性能監視器,NetMon和PerfMon。測試web性能可以用WCAT (Web Capacity Analysis Tool)。使用WCAT,你可以測試你的IIS服務器和網絡配置響應各種各樣的客戶請求,數據或HTML頁面的能力。這些測試結果能夠被用來作爲優化你的服務器和網絡配置的指導。WCAT是專門設計用來估計Windows 2000中(zhōng)的因特網服務(或Windows NT)和IIS 能響應的客戶工(gōng)作量
(仿真)。爲了得到更多的信息,請參閱IIS Resource Kit(資(zī)源工(gōng)具包)。那裏也有冗長的WCAT用戶指南(nán)在MSDN在線Web sorkshop站點裏面有一(yī)個下(xià)載鏈接。如果你認真對待你的Asp 性能的話(huà),務必取得該工(gōng)具。
力求最優化應用程序性能,你的web 應用程序會運行更加順暢。如果不是真正需要,就不要影響服務器的性能。
總結:上面介紹了有關ASP性能的資(zī)料,有很多因素影響Asp的性能,這裏隻讨論了其中(zhōng)的一(yī)部分(fēn)。作爲最終的想法,不要認爲你能夠處理好所有的因素,你的ASP 性能還是有必要提高的。你發布的每個應用程序必須個别進行考慮,所有以上的技巧并不是适合每個Asp程序。
|