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