提高ASP性能的最佳選擇(續(xù)3)
發(fā)表時(shí)間:2024-02-26 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]引用記錄集中域值的最有效方法是什么? 到目前為止,我都是用名字引用記錄集中的域值的。這可能是一種效率很低的方法,因?yàn)槊看握{(diào)用都需要查找域。為了證明這一點(diǎn),下面的測(cè)試就要通過(guò)記錄集中域的集合的指針來(lái)引用域(ADO__08.asp): 'write data Do While No...
引用記錄集中域值的最有效方法是什么?
到目前為止,我都是用名字引用記錄集中的域值的。這可能是一種效率很低的方法,因?yàn)槊看握{(diào)用都需要查找域。為了證明這一點(diǎn),下面的測(cè)試就要通過(guò)記錄集中域的集合的指針來(lái)引用域(ADO__08.asp):
'write data
Do While Not objRS.EOF
Response.Write( _
"< TR >" & _
"< TD >" & objRS(0) & "< /TD >" & _
"< TD >" & objRS(1) & "< /TD >" & _
"< TD >" & objRS(2) & "< /TD >" & _
"< TD >" & objRS(3) & "< /TD >" & _
"< TD >" & objRS(4) & "< /TD >" & _
"< TD >" & objRS(5) & "< /TD >" & _
"< TD >" & objRS(6) & "< /TD >" & _
"< /TR > " _
)
objRS.MoveNext
Loop
正如我們所預(yù)料的,裝載時(shí)間的變化很。ú町惪赡苁怯捎诖a上的輕微減少引起的)。但是這種技術(shù)在有效顯示時(shí)間上卻帶來(lái)了明顯的減少。
在下面的例子中,我們將給每個(gè)域指定一個(gè)單獨(dú)的變量。這種方法避免了在表格循環(huán)內(nèi)的所有查找( ADO__09.asp ):
If objRS.EOF Then
Response.Write("No Records Found")
Else
'write headings
...
Dim fld0
Dim fld1
Dim fld2
Dim fld3
Dim fld4
Dim fld5
Dim fld6
Set fld0 = objRS(0)
Set fld1 = objRS(1)
Set fld2 = objRS(2)
Set fld3 = objRS(3)
Set fld4 = objRS(4)
Set fld5 = objRS(5)
Set fld6 = objRS(6)
'write data
Do While Not objRS.EOF
Response.Write( _
"< TR >" & _
"< TD >" & fld0 & "< /TD >" & _
"< TD >" & fld1 & "< /TD >" & _
"< TD >" & fld2 & "< /TD >" & _
"< TD >" & fld3 & "< /TD >" & _
"< TD >" & fld4 & "< /TD >" & _
"< TD >" & fld5 & "< /TD >" & _
"< TD >" & fld6 & "< /TD >" & _
"< /TR >" _
)
objRS.MoveNext
Loop
Set fld0 = Nothing
Set fld1 = Nothing
Set fld2 = Nothing
Set fld3 = Nothing
Set fld4 = Nothing
Set fld5 = Nothing
Set fld6 = Nothing
Response.Write("< /TABLE >")
End If
到目前,這種方法形成的結(jié)果是最好的。每條記錄的顯示時(shí)間下降成了.45 毫秒。
現(xiàn)在,所有測(cè)試腳本的配置都要求對(duì)結(jié)果記錄集有一些了解。比如說(shuō),我們一直在欄標(biāo)題中給域名編碼,單獨(dú)地引用這些域的值。下面的例子提供了一個(gè)動(dòng)態(tài)的解決方案,在域的集合中循環(huán),不僅得到數(shù)據(jù),也得到域的標(biāo)題(ADO__10.asp ):
If objRS.EOF Then
Response.Write("No Records Found")
Else
'write headings
Response.Write("< TABLE BORDER=1 >< TR >")
For Each objFld in objRS.Fields
Response.Write("< TH >" & objFld.name & "< /TH >")
Next
Response.Write("< /TR >")
'write data
Do While Not objRS.EOF
Response.Write("< TR >")
For Each objFld in objRS.Fields
Response.Write("< TD >" & objFld.value & "< /TD >")
Next
Response.Write("< /TR >")
objRS.MoveNext
Loop
Response.Write("< /TABLE >")
End If
可以看到,我們?cè)谛阅苌嫌幸粋(gè)損失,但是這個(gè)方法還是比ADO__07.asp要快一些。
下面的測(cè)試是在最后兩個(gè)測(cè)試之間進(jìn)行一些折中。通過(guò)在一個(gè)動(dòng)態(tài)分配數(shù)組中保存域的引用,既維持了動(dòng)態(tài)的靈活性,也挽回了一些性能上的損失。
If objRS.EOF Then
Response.Write("No Records Found")
Else
Dim fldCount
fldCount = objRS.Fields.Count
Dim fld()
ReDim fld(fldCount)
Dim i
For i = 0 to fldCount-1
Set fld(i) = objRS(i)
Next
'write headings
Response.Write("< TABLE BORDER=1 >< TR >")
For i = 0 to fldCount-1
Response.Write("< TH >" & fld(i).name & "< /TH >")
Next
Response.Write("< /TR >")
'write data
Do While Not objRS.EOF
Response.Write("< TR >")
For i = 0 to fldCount-1
Response.Write("< TD >" & fld(i) & "< /TD >")
Next
Response.Write("< /TR >")
objRS.MoveNext
Loop
For i = 0 to fldCount-1
Set fld(i) = Nothing
Next
Response.Write("< /TABLE >")
End If
雖然它并不比最好值快,但是比前面的幾個(gè)例子要快了很多,并且有一個(gè)優(yōu)勢(shì)就是能夠動(dòng)態(tài)地表現(xiàn)任何記錄集。
在下一個(gè)測(cè)試中,我們將對(duì)以前的方案做一個(gè)徹底的改變,使用記錄集的GetRows指令創(chuàng)建一個(gè)循環(huán)用的數(shù)組,而不是在記錄集本身進(jìn)行循環(huán)。注意,調(diào)用GetRows之后,立刻就將記錄集設(shè)置為Nothing,這樣就能更快地釋放系統(tǒng)資源。另外還要注意數(shù)組的第一個(gè)維數(shù)代表域,第二個(gè)維數(shù)代表行 ( ADO__12.asp ):
If objRS.EOF Then
Response.Write("No Records Found")
objRS.Close
Set objRS = Nothing
Else
'write headings
...
'set array
Dim arrRS
arrRS = objRS.GetRows
'close recordset early
objRS.Close
Set objRS = Nothing
'write data
Dim numRows
Dim numFlds
Dim row
Dim fld
numFlds = Ubound(arrRS, 1)
numRows = Ubound(arrRS, 2)
For row= 0 to numRows
Response.Write("< TR >")
For fld = 0 to numFlds
Response.Write("< TD >" & arrRS(fld, row) & "< /TD >")
Next
Response.Write("< /TR >")
Next
Response.Write("< /TABLE >")
End If
通過(guò)使用GetRows 指令,就可以獲取整個(gè)記錄集并將其裝載到數(shù)組中。當(dāng)恢復(fù)特別大的記錄集時(shí),這種方法有可能會(huì)造成資源問(wèn)題,但是數(shù)據(jù)的循環(huán)快多了,因?yàn)轭?lèi)似于MoveNext 的函數(shù)調(diào)用和EOF 的檢測(cè)都可以取消了。
不過(guò)速度的提升確實(shí)是有代價(jià)的,因?yàn)橛涗浖脑獢?shù)據(jù)不再與數(shù)據(jù)在一起。圍繞這個(gè)問(wèn)題,我在調(diào)用GetRows之前用記錄集來(lái)恢復(fù)標(biāo)題名。另外還可以提前提取數(shù)據(jù)類(lèi)型和其它信息。還要注意,在我們的測(cè)試中,性能上的優(yōu)勢(shì)只有在使用大一些的記錄集時(shí)才能看到。
在這部分最后的測(cè)試中,我們更進(jìn)一步,使用記錄集的GetString 指令。這個(gè)方法將整個(gè)記錄集提取到一個(gè)大的字符串中,允許你指定自己的分隔符( ADO__13.asp ):
If objRS.EOF Then
Response.Write("No Records Found")
objRS.Close
Set objRS = Nothing
Else
'write headings
...
'set array
Dim strTable
strTable = objRS.GetString (2, , "< /TD >< TD >", "< /TD >< /TR >< TR >< TD >")
'close recordset early
objRS.Close
Set objRS = Nothing
Response.Write(strTable & "< /TD >< /TR >< /TABLE >")
End If
雖然這種方法已經(jīng)接近了最高水平,但是它只適合于最簡(jiǎn)單的設(shè)計(jì),因?yàn)樗揪筒荒軕?yīng)用于數(shù)據(jù)的特殊情況。
觀察
在我們開(kāi)始這套測(cè)試之前,執(zhí)行每條記錄的時(shí)間一直在.83 毫秒左右震動(dòng)。這套測(cè)試中的大多數(shù)方法都將這個(gè)數(shù)字減少了一半。雖然有些方法明顯地提供了更快的速度,但是代價(jià)是靈活性的降低。
下面的規(guī)則是以重要程度為順序的:
* 當(dāng)記錄集中的值不需要用一種特殊方式來(lái)對(duì)待并且能夠格式化為一種統(tǒng)一的格式時(shí),使用GetString方法來(lái)提取數(shù)據(jù)。
* 當(dāng)你在設(shè)計(jì)上需要更大的靈活性,但是又不需要用記錄集的元數(shù)據(jù)進(jìn)行工作,使用GetRows 方法將數(shù)據(jù)提取到一個(gè)數(shù)組中。
* 當(dāng)你需要設(shè)計(jì)的靈活性和元數(shù)據(jù)時(shí),在進(jìn)入一個(gè)數(shù)據(jù)恢復(fù)的循環(huán)之前,將你的域約束在本地變量中。避免用名字引用域。
使用臨時(shí)字符串可以較好地代替緩沖器嗎?
這是針對(duì)我上一篇文章提交的一些注解所引發(fā)的一個(gè)小小的離題。要討論的問(wèn)題是圍繞著緩沖器的使用及使用臨時(shí)字符串作為替代來(lái)收集輸出,這樣就允許Response.Write 只調(diào)用一次。為了測(cè)試,我從ADO_11.asp的代碼開(kāi)始,將結(jié)果附加到一個(gè)字符串中,而不是在每個(gè)循環(huán)都調(diào)用Response.Write,當(dāng)整個(gè)操作都結(jié)束后,在字符串上調(diào)用Response.Write ( STR__01.asp ):
Dim strTable
strTable = ""
'write headings
strTable = strTable & "< TABLE BORDER=1 >< TR >"
For i = 0 to fldCount-1
strTable = strTable & "< TH >" & fld(i).name & "< /TH >"
Next
strTable = strTable & "< /TR >"
'write data
Do While Not objRS.EOF
strTable = strTable & "< TR >"
For i = 0 to fldCount-1
strTable = strTable & "< TD >" & fld(i) & "< /TD >"
Next
strTable = strTable & "< /TR >"
objRS.MoveNext
Loop
For i = 0 to fldCount-1
Set fld(i) = Nothing
Next
strTable = strTable & "< /TABLE >"
Response.Write(strTable)
看起來(lái)執(zhí)行得不是很好。也許正象許多人建議的,我們應(yīng)該用Space 指令為這個(gè)字符串指定一些空間,這樣它就不需要在循環(huán)期間總是為自己重新分配空間( STR__02.asp ):
Dim strTable
strTable = Space(10000)
也許Space 指令并不象建議的那樣工作。我們最后的規(guī)則是:不要用臨時(shí)字符串來(lái)收集輸出。