明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

二108條改善 ASP 性能與外觀的技巧(15-21)

[摘要]技巧 15:批處理內(nèi)嵌腳本和 Response.Write 語(yǔ)句 技巧 16:如果頁(yè)面需要很長(zhǎng)時(shí)間才能完成,那么執(zhí)行前使用 Response.IsClientConnected 技巧 17:使用 <OBJECT> 標(biāo)記例示對(duì)象 技巧 18:對(duì)于 ADO 和其它組件使用 TypeLib ...
技巧 15:批處理內(nèi)嵌腳本和 Response.Write 語(yǔ)句
技巧 16:如果頁(yè)面需要很長(zhǎng)時(shí)間才能完成,那么執(zhí)行前使用 Response.IsClientConnected
技巧 17:使用 <OBJECT> 標(biāo)記例示對(duì)象
技巧 18:對(duì)于 ADO 和其它組件使用 TypeLib 綁定
技巧 19:利用瀏覽器的驗(yàn)證功能
技巧 20:避免在循環(huán)語(yǔ)句中使用字符串串聯(lián)
技巧 21:?jiǎn)⒂脼g覽器和代理緩存
技巧 15:批處理內(nèi)嵌腳本和 Response.Write 語(yǔ)句
VBScript 語(yǔ)法 <% = expression %> 將“expression”的值寫(xiě)到 ASP 輸出流中。如果響應(yīng)緩沖未啟用,那么執(zhí)行其中的每一條語(yǔ)句,都會(huì)以許多小的數(shù)據(jù)包通過(guò)網(wǎng)絡(luò)將數(shù)據(jù)寫(xiě)到瀏覽器中。這樣速度很慢。而且穿插執(zhí)行少量的腳本和 HTML,將引起腳本引擎和 HTML 之間的切換,從而降低性能。因此,使用下面的技巧:使用 Response.Write 調(diào)用代替捆綁緊密的內(nèi)嵌表達(dá)式。例如,在下面的示例中,在每一行的每一字段對(duì)響應(yīng)流有一次寫(xiě)操作,每一行在 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>


下面的代碼更有效,每一行對(duì)響應(yīng)流有一次寫(xiě)操作。所有的代碼都包含在一個(gè) VBScript 塊內(nèi):

<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>


當(dāng)禁用響應(yīng)緩沖時(shí),這一技巧的效果特別大。最好啟用響應(yīng)緩沖,然后看批處理 Response.Write 是否有助于提高性能。

(在這一特定舉例中,建立表主體的嵌套循環(huán) (While Not rs.EOF...) 可以用仔細(xì)構(gòu)建的 GetString 調(diào)用來(lái)替代。)

技巧 16:如果頁(yè)面需要很長(zhǎng)時(shí)間才能完成,那么執(zhí)行前使用 Response.IsClientConnected
如果用戶性急,他們可能會(huì)在您開(kāi)始執(zhí)行他們的請(qǐng)求之前,就會(huì)放棄 ASP 頁(yè)面。如果他們單擊刷新或移到服務(wù)器上的另一個(gè)頁(yè)面,在 ASP 請(qǐng)求隊(duì)列的末尾就有一個(gè)新的請(qǐng)求等候,在隊(duì)列的中間有一個(gè)斷開(kāi)連接的請(qǐng)求。當(dāng)服務(wù)器的負(fù)載很高時(shí)(因此請(qǐng)求隊(duì)列就會(huì)很長(zhǎng),響應(yīng)時(shí)間也會(huì)相應(yīng)地變長(zhǎng)),就會(huì)經(jīng)常發(fā)生這種情況,這樣只能使情況變得更糟。如果用戶不再連接,執(zhí)行 ASP 頁(yè)面(特別是慢的、大的 ASP 頁(yè)面)已沒(méi)有任何意義。您可以使用 Response.IsClientConnected 屬性檢查這一情況。如果它返回 False,則應(yīng)調(diào)用 Response.End 并放棄頁(yè)的其余部分。事實(shí)上,IIS 5.0 已將這一做法編為程序 - 每當(dāng) ASP 即將執(zhí)行新請(qǐng)求時(shí),它就會(huì)檢查請(qǐng)求在隊(duì)列中已等候了多長(zhǎng)時(shí)間。如果已經(jīng)在那里等候了多于 3 秒鐘,ASP 將檢查客戶機(jī)是否仍處于連接狀態(tài),如果沒(méi)有連接,就立即終止請(qǐng)求。您可以在配置數(shù)據(jù)庫(kù)中使用 AspQueueConnectionTestTime 設(shè)置將超時(shí)時(shí)間由 3 秒調(diào)整為其它值。

如果頁(yè)面要花很長(zhǎng)時(shí)間才能執(zhí)行完,也可以不時(shí)地檢查 Response.IsClientConnected。當(dāng)啟用了響應(yīng)緩沖時(shí),最好不時(shí)地執(zhí)行 Response.Flush,以用戶知道,正在發(fā)生什么事。

注意 在 IIS 4.0 上,除非先執(zhí)行了 Response.Write,否則 Response.IsClientConnected 就不能正常工作。如果啟用了緩沖,您也必須執(zhí)行 Response.Flush。在 IIS 5.0 上,卻沒(méi)有必要這樣做,- Response.IsClientConnected 工作正常。在任何情況下,Response.IsClientConnected 都會(huì)有一些開(kāi)銷(xiāo),因此只有在一個(gè)操作至少要花(比方說(shuō)) 500 毫秒(如果您想維持每秒鐘數(shù)十頁(yè)的吞吐量,這是一個(gè)很長(zhǎng)的時(shí)間)才使用它。經(jīng)驗(yàn)表明,不要每次重復(fù)執(zhí)行緊密循環(huán)時(shí)都調(diào)用它,如顯示表的許多行時(shí) - 每隔二十或五十行調(diào)用一次可能比較合適。

技巧 17:使用 <OBJECT> 標(biāo)記例示對(duì)象
如果要引用不在所有代碼路徑(特別是服務(wù)器或應(yīng)用程序作用域的對(duì)象)中使用的對(duì)象,使用 Global.asa 中 <object runat=server id=objname> 標(biāo)記聲明它們,而不使用 Server.CreateObject 方法。Server.CreateObject 能立即創(chuàng)建對(duì)象。如果以后不再使用該對(duì)象,您就浪費(fèi)了資源。<object id=objname> 標(biāo)記聲明 objname,但在其方法或?qū)傩缘谝淮问褂靡郧,不?huì)創(chuàng)建 objname。

這又是一個(gè)惰性計(jì)算的例子。

技巧 18:對(duì)于 ADO 和其它組件使用 TypeLib 聲明
當(dāng)使用 ADO 時(shí),開(kāi)發(fā)人員經(jīng)常加入 adovbs.txt,以訪問(wèn) ADO 的各種常量。在要使用常量的每個(gè)頁(yè)面中必須包含此文件。此常量文件相當(dāng)大,給每個(gè) ASP 頁(yè)面的編譯時(shí)間和腳本大小增加了許多系統(tǒng)開(kāi)銷(xiāo)。

IIS 5.0 引入了綁定到組件類(lèi)型庫(kù)的功能。這可使您引用類(lèi)型庫(kù)一次,并將其用在每個(gè) ASP 頁(yè)面上。每個(gè)頁(yè)面不會(huì)產(chǎn)生編譯常量文件的開(kāi)銷(xiāo),且組件開(kāi)發(fā)人員不必建立 VBScript#_include 文件以在 ASP 上使用。

要訪問(wèn) ADO TypeLib,將下面一條語(yǔ)句放在 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: 利用瀏覽器的驗(yàn)證功能
現(xiàn)今的瀏覽器對(duì)一些高級(jí)功能如 XML、DHTML、Java 小程序和遠(yuǎn)程數(shù)據(jù)服務(wù)提供支持。盡可能使用這些功能。所有這些技術(shù)都可以執(zhí)行客戶機(jī)端驗(yàn)證和數(shù)據(jù)緩存,免去了到 Web 服務(wù)器的往返。如果您在運(yùn)行一個(gè)智能瀏覽器,那么瀏覽器就能為您進(jìn)行一些驗(yàn)證(例如,在執(zhí)行 POST 之前,檢查信用卡校驗(yàn)和是否有效)。盡可能使用這一功能。通過(guò)減少客戶-服務(wù)器之間的往返,可降低 Web 服務(wù)器上的負(fù)載,并能減少網(wǎng)絡(luò)通信量(雖然發(fā)送到瀏覽器的第一個(gè)頁(yè)面可能比較大)以及服務(wù)器訪問(wèn)的任何后端資源。此外,用戶不必像住常一樣讀取新頁(yè),從而用戶的感覺(jué)會(huì)好一些。這樣做并不意味著您可以不進(jìn)行服務(wù)器端驗(yàn)證 - 您還應(yīng)始終進(jìn)行服務(wù)器端驗(yàn)證。這可以防止由于某種原因(如黑客,或?yàn)g覽器不運(yùn)行客戶機(jī)端驗(yàn)證例程)客戶機(jī)產(chǎn)生錯(cuò)誤的數(shù)據(jù)。

人們已經(jīng)進(jìn)行了大量的工作,開(kāi)發(fā)“獨(dú)立于瀏覽器”的 HTML。正是由于這種憂慮,開(kāi)發(fā)人員不愿再使用流行的瀏覽器功能,但這些功能本可以改善性能。對(duì)于一些真正的高性能站點(diǎn),必須關(guān)心瀏覽器“訪問(wèn)”問(wèn)題,一個(gè)好的策略是優(yōu)化頁(yè)面,使其適應(yīng)流行的瀏覽器。使用瀏覽器功能組件,可以在 ASP 中方便地檢測(cè)到瀏覽器功能。Microsoft FrontPage 等工具有助于設(shè)計(jì)適合于瀏覽器和指定 HTML 版本的代碼。參見(jiàn) When is Better Worse?Weighing the Technology Trade-Offs,以了解更進(jìn)一步的討論。

技巧 20:避免在循環(huán)語(yǔ)句中使用字符串串聯(lián)
許多人在循環(huán)語(yǔ)句中建立一個(gè)字符串,如下所示:

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


采用這種方法會(huì)出現(xiàn)一些問(wèn)題。第一個(gè)問(wèn)題是反復(fù)串聯(lián)字符串需要花兩次方的時(shí)間,更通俗地說(shuō),運(yùn)行這種循環(huán)語(yǔ)句所花的時(shí)間與記錄數(shù)乘以字段數(shù)所得值的平方成正比。舉一個(gè)更簡(jiǎn)單的例子,就可以更清楚地說(shuō)明這一問(wèn)題。

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


在第一次迭代中,您獲得了一個(gè)字符的字符串 ?A?。在第二次迭代中,VBScript 必須重新分配字符串并將兩個(gè)字符 (?AB?) 復(fù)制到 s 中。在第三次迭代中,它還必須再次重新分配 s 并將三個(gè)字符復(fù)制到 s 中。在 N 次(第 26 次)迭代中,它必須重新分配并將 N 個(gè)字符復(fù)制到 s 中?偣簿褪 1+2+3+...+N,即 N*(N+1)/2 次復(fù)制。

在上面的記錄集舉例中,如果有 100 個(gè)記錄和 5 個(gè)字段,內(nèi)循環(huán)將執(zhí)行 100*5 = 500 次,所有的復(fù)制和重新分配所花的時(shí)間與 500*500 = 250,000 成正比。這對(duì)于中等大小的記錄集來(lái)說(shuō)復(fù)制操作太多了。

在本例中,代碼可以用 Response.Write() 或內(nèi)嵌腳本 (<% = fld.Value %>) 替代字符串串聯(lián)來(lái)改進(jìn)。如果啟用了響應(yīng)緩沖的話(應(yīng)該的),這樣做就會(huì)更快,因?yàn)?Response.Write 只將數(shù)據(jù)附加到響應(yīng)緩沖的末尾。并不涉及重新分配,因此效率很高。

在將 ADO 記錄集轉(zhuǎn)換為 HTML 表的特定情況下,應(yīng)考慮使用 GetRows 或 GetString。

如果在 JScript 中串聯(lián)字符串,特別建議使用 += 運(yùn)算符,即,使用 s += ?某字符串?,而不使用 s = s + ?某字符串?。

技巧 21:?jiǎn)⒂脼g覽器和代理緩存
在默認(rèn)情況下,ASP 禁止在瀏覽器和代理中進(jìn)行緩存。這是有意義的,因?yàn)榫蛯?shí)質(zhì)而言 ASP 頁(yè)面是動(dòng)態(tài)的,上面有隨時(shí)間不斷變化的潛在信息。如果頁(yè)面不要求在每個(gè)視圖上進(jìn)行刷新,您應(yīng)啟用瀏覽器和代理緩存。這可使瀏覽器和代理在一定的時(shí)間內(nèi)使用頁(yè)面的“緩存”副本,您可以控制時(shí)間的長(zhǎng)短。緩存可以大大減輕服務(wù)器上的負(fù)載,縮短用戶的等待時(shí)間。

哪一種動(dòng)態(tài)頁(yè)面可作為要緩存的頁(yè)面呢?下面舉一些例子:

天氣預(yù)報(bào)頁(yè)面,在此頁(yè)面上,每隔 5 分鐘更新一次天氣預(yù)報(bào)。
列出新聞條目或新聞稿的主頁(yè),它一天更新兩次。
共同基金業(yè)績(jī)列表,在此列表中,基本統(tǒng)計(jì)信息每隔幾小時(shí)更新一次。
注意,在使用瀏覽器或代理緩存的情況下,Web 服務(wù)器上記錄的訪問(wèn)次數(shù)減少了。如果您想準(zhǔn)確地測(cè)量所有頁(yè)面視圖或張?zhí),您就不希望使用瀏覽器和代理緩存。

瀏覽器緩存由 HTTP“過(guò)期”報(bào)頭控制,該報(bào)頭由 Web 服務(wù)器發(fā)送給瀏覽器。ASP 提供兩個(gè)簡(jiǎn)單的機(jī)制發(fā)送此報(bào)頭。要設(shè)置頁(yè)面使其過(guò)多少分鐘后到期,則應(yīng)設(shè)置 Response.Expires 屬性。下面的例子告訴瀏覽器內(nèi)容在 10 分鐘內(nèi)過(guò)期:

<% Response.Expires = 10 %>


若將 Response.Expires 設(shè)置為負(fù)數(shù)或 0,則禁用緩存。一定要使用大的負(fù)數(shù),如 -1000(略多于一天),以避免服務(wù)器和瀏覽器時(shí)鐘之間的不匹配。第二個(gè)屬性 Response.ExpiresAbsolute 將使您設(shè)置內(nèi)容過(guò)期的具體時(shí)間:

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


您可以不使用 Response 對(duì)象設(shè)置過(guò)期時(shí)間,而將 <META> 標(biāo)記寫(xiě)進(jìn) HTML,通常寫(xiě)在 HTML 文件的 <HEAD> 部分。一些瀏覽器將遵照此指令,而代理則不然。

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


最后,您可以使用 Response.CacheControl 屬性,指示其內(nèi)容是否可以讓 HTTP 代理緩存。若將此屬性設(shè)置為“Public”,代理就可以緩存此內(nèi)容。

<% Response.CacheControl = ?Public? %>


在默認(rèn)情況下,此屬性被設(shè)置為“Private”。注意,對(duì)于顯示某用戶特定數(shù)據(jù)的頁(yè)面,不應(yīng)啟用代理緩存,因?yàn)榇砜赡芙o用戶提供屬于其他用戶的頁(yè)面。