ASP中處理#include
發(fā)表時(shí)間:2023-08-20 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]在ASP中處理#include 文件與用編譯高級(jí)編程語(yǔ)言,如C/C++處理包含文件,這兩種方法之間有兩個(gè)主要區(qū)別。第一,ASP不從最終形成的ASP文件中移走那些未涉及到的信息。這是因?yàn)锳SP獨(dú)立于腳...
在ASP中處理#include 文件與用編譯高級(jí)編程語(yǔ)言,如C/C++處理包含文件,這兩種方法之間有兩個(gè)主要區(qū)別。
第一,ASP不從最終形成的ASP文件中移走那些未涉及到的信息。這是因?yàn)锳SP獨(dú)立于腳本引擎,不過(guò)多地進(jìn)行代碼
分析。大體說(shuō)來(lái),如果遇到了ASP文件的基本語(yǔ)法請(qǐng)求,信息就被緩存(假定緩沖器是打開的)并被發(fā)送到適當(dāng)
的腳本引擎,進(jìn)行進(jìn)一步的分解、標(biāo)記及執(zhí)行。
除了這個(gè)“死碼”問(wèn)題,ASP包含文件與編譯語(yǔ)言之間的另一個(gè)區(qū)別在于:每個(gè)ASP文件都可以被看作它自己
的程序。只要一個(gè)頁(yè)面不包含另一個(gè),在ASP的意義上看來(lái)它們就沒(méi)有關(guān)系,盡管二者對(duì)整個(gè)站點(diǎn)的運(yùn)行都很
關(guān)鍵。因此,被兩個(gè)不同頁(yè)面所共享的一個(gè)#include 文件必須要被兩個(gè)文件都完全包含。從本質(zhì)上說(shuō),ASP不具
備許多高級(jí)語(yǔ)言所具備的連接器的優(yōu)勢(shì),連接器可以用來(lái)避免包含文件中代碼和數(shù)據(jù)的冗余。
如果把我所概括的ASP包含文件的問(wèn)題組合起來(lái),結(jié)論就是:它對(duì)一個(gè)大型站點(diǎn)的內(nèi)存將是破壞性的。想象
一下這種情況:一個(gè)包含文件中包含了可能要用到的所有共享程序。按照這種設(shè)計(jì),導(dǎo)致的結(jié)果是所有的ASP頁(yè)
都必須包含這一關(guān)鍵的文件。如果EverythingButTheKitchenSink.inc 經(jīng)過(guò)分解之后與ASP文件的平均長(zhǎng)度相同,
那么被ASP分配并為緩存的ASP文件使用的內(nèi)存中的一半都充滿了本來(lái)多余沒(méi)用的信息。
813
調(diào)用NT Task Manager/Processes 可以看到正被站點(diǎn)所使用著的內(nèi)存,并觀察一下多少內(nèi)存是由mtx.exe
(如果站點(diǎn)被設(shè)置成獨(dú)立的程序在IIS4上運(yùn)行),dllhost.exe (如果站點(diǎn)被設(shè)置成獨(dú)立的程序在IIS5上運(yùn)行),
或是inetinfo.exe (如果不是獨(dú)立的,見下面的圖)這些程序所使用。想要掌握內(nèi)存增加得有多快,一個(gè)很好的
測(cè)試方法是啟動(dòng)IIS后調(diào)用一個(gè)簡(jiǎn)單的頁(yè)面來(lái)看看內(nèi)存的大小。(看內(nèi)存之前要調(diào)用一個(gè)ASP文件,因?yàn)樵谔幚淼?br>一個(gè)ASP文件時(shí)要建立一些普通的通用文件),F(xiàn)在在你的站點(diǎn)上使用其它ASP文件,并監(jiān)控每一個(gè)被使用的ASP文
件對(duì)內(nèi)存的作用。
比如說(shuō)我創(chuàng)建了ASP文件。第一個(gè)文件RunFirst.asp,是一個(gè)小文件,在觀察內(nèi)存之前初始化ASP資源。另外
兩個(gè)文件除了它們所要使用的#include 文件信息不同以外,是完全一樣的。將這些文件復(fù)制到你的wwwroot目錄下,
然后按順序運(yùn)行RunFirst.asp, HelloWorld1.asp和 HelloWorld2.asp,執(zhí)行HelloWorld1.asp和HelloWorld2.asp
之后觀察內(nèi)存,你會(huì)發(fā)現(xiàn)后者使用了更多的內(nèi)存。這是因?yàn)樗褂玫?include 文件中有一個(gè)很大的未使用的程序,
BigAndUnreferenced, 它對(duì)頁(yè)面的運(yùn)行結(jié)果沒(méi)有任何作用,但卻占據(jù)了400K的內(nèi)存。在Windows 2000 Server
w/ IIS5 上依次進(jìn)行下列步驟得到的結(jié)果是:
運(yùn)行RunFirst.asp 后內(nèi)存6,104K
運(yùn)行HelloWorld1.asp后內(nèi)存 6,124K
運(yùn)行HelloWorld2.asp后內(nèi)存 6,544K
僅僅按照這個(gè)順序沒(méi)有什么明顯的意義,顛倒裝載順序之后的結(jié)果是:
運(yùn)行 RunFirst.asp 后內(nèi)存6,096K
運(yùn)行 HelloWorld2.asp后內(nèi)存 6,536K
運(yùn)行 HelloWorld1.asp 后內(nèi)存6,540K
請(qǐng)注意開始和結(jié)束的內(nèi)存數(shù)不完全一致,因?yàn)閮?nèi)存管理器根據(jù)最近的請(qǐng)求大塊地分配內(nèi)存。但是相對(duì)而言,
最終的輪廓總是HelloWorld2.asp 占據(jù)大塊的內(nèi)存份額。本文結(jié)尾處可以下載這些簡(jiǎn)短的代碼。瀏覽以下這些
代碼,但要分清內(nèi)存的不同:
RunFirst.asp 是這樣的:
< %@ LANGUAGE="VBSCRIPT" % >
< HTML >
< HEAD >< TITLE >Seed Page to load general ASP resources< /TITLE >< HEAD >
< BODY >
< %
Response.Write "Seed Page Loaded"
% >
< /BODY >
< /HTML >
HelloWorld1.asp 是這樣的:
< %@ LANGUAGE="VBSCRIPT" % >
< !--#include virtual ="/HelloWorld1.inc"-- >
< HTML >
< HEAD >< TITLE >Hello World using little memory< /TITLE >< HEAD >
< BODY >
< %
SayHello
% >
< /BODY >
< /HTML >
HelloWorld1.inc代碼是:
< %
Sub SayHello
Response.Write "Hello World 1"
End Sub
% >
HelloWorld2.asp代碼是:
< %@ LANGUAGE="VBSCRIPT" % >
< !--#include virtual ="/HelloWorld2.inc"-- >
< HTML >
< HEAD >< TITLE >Hello World using a lot of memory< /TITLE >< HEAD >
< BODY >
< %
SayHello
% >
< /BODY >
< /HTML >
但是HelloWorld2.inc要大一些:
< %
Sub SayHello
Response.Write "Hello World 2"
End Sub
Sub BigAndUnreferenced
' This does a lot of redundant stuff to increase memory
Dim textVar
textVar = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
' this line is duplicated 1,000 times
End Sub
% >
本文中對(duì)內(nèi)存資源的討論是以緩沖器打開為前提的。如果緩沖器沒(méi)有打開,那么每個(gè)ASP文件集中裝載頁(yè)面
的所有組成部分,頁(yè)面執(zhí)行之后再釋放這些內(nèi)容。多數(shù)站點(diǎn)都在一定程度上打開緩沖器,因?yàn)榇罅奎c(diǎn)擊的站點(diǎn)
的運(yùn)行請(qǐng)求這樣的要求。即使由于某種原因不打開緩沖器,仍可能受到#include 文件問(wèn)題的影響,表現(xiàn)為內(nèi)存波動(dòng)較
大和處理速度慢。
這里有一些技巧供你參考使用,如:
重新構(gòu)造包含文件
重新構(gòu)造包含文件可能是目前你所能做的最容易的事。列出所有包含文件,查找問(wèn)題的以下跡象:
○ #include 文件是否包含著多種函數(shù)??jī)?nèi)存效率最高的包含文件應(yīng)該是特定函數(shù)的,以減少死碼的可能性。
例如一個(gè)處理日期和時(shí)間的包含文件,可以把它分成兩個(gè)文件,各處理一個(gè)方面:一個(gè)單獨(dú)的ASP只需要處理一種
類型。
○ #include 文件是否專門存儲(chǔ)整個(gè)應(yīng)用程序所公用的常量?這類文件,根據(jù)其大小,可以導(dǎo)致問(wèn)題發(fā)生,
因?yàn)橥ǔK鼈冃枰话谒械钠渌募校驮斐闪税募短。可以將常量放置在它們所引用?br>包含文件中。如果常量是ASP文件內(nèi)部需要的,就可以創(chuàng)建與它們的使用種類有關(guān)的較小的常量文件。
○ #include 文件中是否包含作廢的函數(shù)?有些函數(shù)/程序是站點(diǎn)過(guò)去使用過(guò)的,已經(jīng)過(guò)了使用期限還掛在那里。
如果在不可預(yù)見的未來(lái)某一時(shí)間,有可能再次使用它們,就應(yīng)該創(chuàng)建一個(gè)小心存檔的文檔文件,說(shuō)明該函數(shù)/程序從
哪里來(lái),何時(shí)被移走的,而不是將他們留在活動(dòng)文件中。版本控制系統(tǒng)對(duì)清除舊資源也有所幫助,因?yàn)樗苋菀?br>被覆蓋。
○ 你對(duì)第三方包含文件了解充分嗎?因?yàn)樯婕暗絻?nèi)存問(wèn)題,你應(yīng)該明白你的包含文件有多大(甚至于那些你
沒(méi)有直接創(chuàng)建的)并且判定一下是否真的需要它們。
你也許會(huì)想,這些削減和修改是否在實(shí)際上增加了包含文件的數(shù)量,在ASP文件中需要更多的#include聲明?
在大多數(shù)情況下,答案是肯定的。這是更好地使用包含文件的代價(jià),但是一旦完成了最初的轉(zhuǎn)換,就不會(huì)增加管
理ASP文件的難度。
將代碼放入對(duì)象中
也許你正在經(jīng)歷由#include 而引起的內(nèi)存膨脹,好在可以在站點(diǎn)中用對(duì)象多做一些工作。如果你堅(jiān)持在
腳本中執(zhí)行函數(shù),可以考慮使用Scriptlet 。在ASPToday站點(diǎn)和其它刊物上有許多文章討論這些技巧。Scriptlet
可以很好地減少所使用的包含文件的數(shù)量:大部分代碼寫完后,從包含函數(shù)到它在對(duì)象中的封裝之間的過(guò)渡
相當(dāng)容易。只需要圍繞現(xiàn)有代碼的幾句額外的語(yǔ)法和調(diào)用方法的一些改變,就完成了對(duì)象。另一個(gè)優(yōu)勢(shì)在于
scriptlet對(duì)象本身就可以被共享,從而進(jìn)一步減少內(nèi)存需求。
如果你想要更大的改變,可以考慮可以移植到更快的編譯語(yǔ)言,如like VB, VC++/ATL, 或 Delphi 上的
函數(shù)。這樣一來(lái)你的應(yīng)用程序速度真的得到了提高,因?yàn)檫@時(shí)所執(zhí)行的是最優(yōu)化的代碼而不是解釋腳本。這種
轉(zhuǎn)變的復(fù)雜性顯然依所選語(yǔ)言而不同。比如說(shuō),從VBScript 到 VB 就非常直接,而從VBScript 到 VC++/ATL
就復(fù)雜多了?梢韵茸鞒蓅criptlet,然后取幾個(gè)這樣的新對(duì)象并將它們移到編譯語(yǔ)言中去。最好的選擇要么
是很大的對(duì)象,它可以節(jié)省內(nèi)存,要么就是使用最頻繁的對(duì)象,它可以相當(dāng)?shù)靥岣咝阅堋?br>
不管你使用什么語(yǔ)言,使用對(duì)象都可以幫助IIS優(yōu)化管理機(jī)器資源,因?yàn)檫@時(shí)是在MTS 下運(yùn)行,并利用它的
所有優(yōu)勢(shì):連接pooling、對(duì)象共享及其它。
利用Server.Execute 和 Server.Transfer (僅限于ASP3/IIS5)
有一個(gè)好消息是Microsoft已經(jīng)認(rèn)識(shí)到了這些問(wèn)題,正在用IIS5帶的ASP3提供解決這些問(wèn)題的新技術(shù)。有
兩種新的服務(wù)器方法可以把你從過(guò)多的包含文件中解脫出來(lái)。它們使用同一個(gè)自變量:ASP文件名。Server.Execute
調(diào)用所提供的ASP文件,執(zhí)行并返回調(diào)用者。Server.Transfer 將控制轉(zhuǎn)換到提供的ASP文件,但不返回。兩個(gè)
調(diào)用運(yùn)行文件的方式就好象它們?cè)谡{(diào)用者ASP應(yīng)用程序內(nèi)。最后這一點(diǎn)很重要,因?yàn)楝F(xiàn)有的文件規(guī)定可以從其它
應(yīng)用程序中調(diào)用ASP文件。
這些調(diào)用的思路是將公用的程序放入ASP文件中,然后在其它ASP文件中需要的地方直接執(zhí)行它們。這類似于
動(dòng)態(tài)的#include ,在調(diào)用頁(yè)中不使用額外內(nèi)存。他們非常有效,因?yàn)閳?zhí)行的獨(dú)立的ASP文件,擁有被緩存和被
共享的一切有利條件。而對(duì)包含文件中的公用程序而言,每個(gè)使用它們的ASP文件都要裝載并要保留一份拷貝。
Server.Execute 的一個(gè)很好的特點(diǎn)是運(yùn)行條件包含的能力。通常情況下包含不能是有條件的,因?yàn)?include
指示是在腳本代碼執(zhí)行處理?xiàng)l件之前預(yù)先處理的。但是用Server.Execute 可以寫出這樣的代碼,查看一個(gè)
session變量,決定調(diào)用哪一部分代碼,而不是總是裝載著兩部分代碼。
If Session("DoThisOrThat") = "this" Then
Server.Execute("this.asp")
Else
Server.Execute("that.asp")
End If
如果IIS5發(fā)行后很快你就能使用(甚至于在此之前,如果你敢在你的站點(diǎn)上使用試用版的話),那么你就
不用為削減你的包含文件而太擔(dān)心,相反應(yīng)該把時(shí)間花在模塊化成可直接調(diào)用的ASP文件上,或者象上面所說(shuō)
的將代碼移入對(duì)象中。
總結(jié)
包含文件的核心思想是:它們是共享代碼的最簡(jiǎn)單方式之一,并且能簡(jiǎn)化模式站點(diǎn)的設(shè)計(jì)。我曾經(jīng)使用過(guò)的所
有的先進(jìn)編程語(yǔ)言都有共享源文件的方法,ASP腳本模型也不例外。一個(gè)通用的規(guī)則是,傾向于使用包含文件而不是克
隆代碼,但是考慮到ASP在IIS下處理內(nèi)存空間的獨(dú)特方式,注意到這個(gè)問(wèn)題是值得的。
注意在此提到的在站點(diǎn)縮小占用內(nèi)存的方法。用Task Manager 或類似的工具來(lái)觀察mtx.exe (IIS4),
dllhost.exe (IIS5)或 inetinfo,exe (IIS4/5) 的內(nèi)存大小。你會(huì)因一個(gè)效率更高的運(yùn)行站點(diǎn)受益,你的
系統(tǒng)管理員也會(huì)因?yàn)楣?jié)省出來(lái)的內(nèi)存芯片而高興。