<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    The NoteBook of EricKong

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks
    簡介
      
      編寫 ASP 頁面時,開發(fā)人員實際上是創(chuàng)建一個格式化的文本流,通過 ASP 提供的 Response 對象寫入 Web 客戶端。創(chuàng)建此文本流的方法有多種,而您選擇的方法將對 Web 應用程序的性能和可縮放性產生很大影響。很多次,在我?guī)椭蛻魞?yōu)化其 Web 應用程序的性能時,發(fā)現(xiàn)其中一個比較有效的方法是更改 HTML 流的創(chuàng)建方式。本文將介紹幾種常用技術,并測試它們對一個簡單的 ASP 頁面的性能所產生的影響。
      
      ASP 設計
      
      許多 ASP 開發(fā)人員都遵循良好的軟件工程原則,盡可能地將其代碼模塊化。這種設計通常使用一些包含文件,這些文件中包含對頁面的特定不連續(xù)部分進行格式化生成的函數(shù)。這些函數(shù)的字符串輸出(通常是 HTML 表格代碼)可以通過各種組合創(chuàng)建一個完整的頁面。某些開發(fā)人員對此方法進行了改進,將這些 HTML 函數(shù)移到 Visual Basic COM 組件中,希望充分利用已編譯的代碼提供的額外性能。
      
      盡管這種設計方法很不錯,但創(chuàng)建組成這些不連續(xù) HTML 代碼組件的字符串所使用的方法將對 Web 站點的性能和可縮放性產生很大的影響,無論實際的操作是在 ASP 包含文件中執(zhí)行還是在 Visual Basic COM 組件中執(zhí)行。
      
      字符串連接
      
      請看以下 WriteHTML 函數(shù)的代碼片斷。名為 Data 的參數(shù)只是一個字符串數(shù)組,其中包含一些要格式化為表格結構的數(shù)據(jù)(例如,從數(shù)據(jù)庫返回的數(shù)據(jù))。
      
      Function WriteHTML( Data )
      Dim nRep
      For nRep = 0 to 99
      sHTML = sHTML & vbcrlf _
      & "<TR><TD>" & (nRep + 1) & "</TD><TD>" _
      & Data( 0, nRep ) & "</TD><TD>" _
      & Data( 1, nRep ) & "</TD><TD>" _
      & Data( 2, nRep ) & "</TD><TD>" _
      & Data( 3, nRep ) & "</TD><TD>" _
      & Data( 4, nRep ) & "</TD><TD>" _
      & Data( 5, nRep ) & "</TD></TR>"
      Next
      WriteHTML = sHTML
      End Function
      
      這是很多 ASP 和 Visual Basic 開發(fā)人員創(chuàng)建 HTML 代碼時常用的方法。sHTML 變量中包含的文本返回到調用代碼,然后使用 Response.Write 寫入客戶端。當然,這還可以表示為直接嵌入不包含 WriteHTML 函數(shù)的頁面的類似代碼。此代碼的問題是,ASP 和 Visual Basic 使用的字符串數(shù)據(jù)類型(BSTR 或 Basic 字符串)實際上無法更改長度。這意味著每當字符串長度更改時,內存中字符串的原始表示形式都將遭到破壞,而且將創(chuàng)建一個包含新字符串數(shù)據(jù)的新的表示形式:這將增加分配內存和解除分配內存的操作。當然,ASP 和 Visual Basic 已為您解決了這一問題,因此實際開銷不會立即顯現(xiàn)出來。分配內存和解除分配內存要求基本運行時代碼解除各個專用鎖定,因此需要大量開銷。當字符串變得很大并且有大塊內存要被快速連續(xù)地分配和解除分配時,此問題變得尤為明顯,就像在大型字符串連接期間出現(xiàn)的情況一樣。盡管這一問題對單用戶環(huán)境的影響不大,但在服務器環(huán)境(例如,在 Web 服務器上運行的 ASP 應用程序)中,它將導致嚴重的性能和可縮放性問題。
      
      下面,我們回到上述代碼片段:此代碼中要執(zhí)行多少個字符串分配操作?答案是 16 個。在這種情況下,“&”運算符的每次應用都將導致變量 sHTML 所指的字符串被破壞和重新創(chuàng)建。前面已經提到,字符串分配的開銷很大,并且隨著字符串的增大而增加,因此,我們可以對上述代碼進行改進。
      
      快捷的解決方案
      
      有兩種方法可以緩解字符串連接的影響,第一種方法是嘗試減小要處理的字符串的大小,第二種方法是嘗試減少執(zhí)行字符串分配操作的數(shù)目。請參見下面所示的 WriteHTML 代碼的修訂版本。
      
      Function WriteHTML( Data )
      
      Dim nRep
      
      For nRep = 0 to 99
      sHTML = sHTML & ( vbcrlf _
      & "<TR><TD>" & (nRep + 1) & "</TD><TD>" _
      & Data( 0, nRep ) & "</TD><TD>" _
      & Data( 1, nRep ) & "</TD><TD>" _
      & Data( 2, nRep ) & "</TD><TD>" _
      & Data( 3, nRep ) & "</TD><TD>" _
      & Data( 4, nRep ) & "</TD><TD>" _
      & Data( 5, nRep ) & "</TD></TR>" )
      Next
      
      WriteHTML = sHTML
      
      End Function
      
      乍一看,可能很難發(fā)現(xiàn)這段代碼與上一個代碼示例的差別。其實,此代碼只是在 sHTML = sHTML & 后的內容外面加上了括號。這實際上是通過更改優(yōu)先順序,來減小大多數(shù)字符串連接操作中處理的字符串大小。在最初的代碼示例中,ASP 編譯器將查看等號右邊的表達式,并從左到右進行計算。結果,每次重復都要進行 16 個連接操作,這些操作針對不斷增長的 sHTML 進行。在新版本中,我們提示編譯器更改操作順序。現(xiàn)在,它將按從左到右、從括號內到括號外的順序計算表達式。此技術使得每次重復包括 15 個連接操作,這些操作針對的是不會增長的較小字符串,只有一個是針對不斷增長的大的 sHTML。圖 1 顯示了這種優(yōu)化方法與標準連接方法在內存使用模式方面的比較。
      
     

      
    圖 1:標準連接與加括號連接在內存使用模式方面的比較

      
      在特定情況下,使用括號可以對性能和可縮放性產生十分顯著的影響,后文將對此進行進一步的說明。
      
      StringBuilder
      
      我們已經找到了解決字符串連接問題的快捷方法,在多數(shù)情況下,此方法可以達到性能和投入的最佳平衡。但是,如果要進一步提高構建大型字符串的性能,需要采用第二種方法,即減少字符串分配操作的數(shù)目。為此,需要使用 StringBuilder。StringBuilder 是一個類,用于維護可配置的字符串緩沖區(qū),管理插入到此緩沖區(qū)的新文本片斷,并僅在文本長度超出字符串緩沖區(qū)長度時對字符串進行重新分配。Microsoft .NET 框架免費提供了這樣一個類 (System.Text.StringBuilder),并建議在該環(huán)境下進行的所有字符串連接操作中使用它。在 ASP 和傳統(tǒng)的 Visual Basic 環(huán)境中,我們無法訪問此類,因此需要自行創(chuàng)建。下面是使用 Visual Basic 6.0 創(chuàng)建的 StringBuilder 類示例(為簡潔起見,省略了錯誤處理代碼)。
      
      Option Explicit
      
      ' 默認的緩沖區(qū)初始大小和增長系數(shù)
      Private Const DEF_INITIALSIZE As Long = 1000
      Private Const DEF_GROWTH As Long = 1000
      
      ' 緩沖區(qū)大小和增長
      Private m_nInitialSize As Long
      Private m_nGrowth As Long
      
      ' 緩沖區(qū)和緩沖區(qū)計數(shù)器
      Private m_sText As String
      Private m_nSize As Long
      Private m_nPos As Long
      
      Private Sub Class_Initialize()
      ' 設置大小和增長的默認值
      m_nInitialSize = DEF_INITIALSIZE
      m_nGrowth = DEF_GROWTH
      ' 初始化緩沖區(qū)
      InitBuffer
      End Sub
      
      ' 設置初始大小和增長數(shù)量
      Public Sub Init(ByVal InitialSize As Long, ByVal Growth As Long)
      If InitialSize > 0 Then m_nInitialSize = InitialSize
      If Growth > 0 Then m_nGrowth = Growth
      End Sub
      
      ' 初始化緩沖區(qū)
      Private Sub InitBuffer()
      m_nSize = -1
      m_nPos = 1
      End Sub
      
      ' 增大緩沖區(qū)
      Private Sub Grow(Optional MinimimGrowth As Long)
      ' 初始化緩沖區(qū)(如有必要)
      If m_nSize = -1 Then
      m_nSize = m_nInitialSize
      m_sText = Space$(m_nInitialSize)
      Else
      ' 只是增長
      Dim nGrowth As Long
      nGrowth = IIf(m_nGrowth > MinimimGrowth,
      m_nGrowth, MinimimGrowth)
      m_nSize = m_nSize + nGrowth
      m_sText = m_sText & Space$(nGrowth)
      End If
      End Sub
      
      ' 將緩沖區(qū)大小調整到當前使用的大小
      Private Sub Shrink()
      If m_nSize > m_nPos Then
      m_nSize = m_nPos - 1
      m_sText = RTrim$(m_sText)
      End If
      End Sub
      
      ' 添加單個文本字符串
      Private Sub AppendInternal(ByVal Text As String)
      If (m_nPos + Len(Text)) > m_nSize Then Grow Len(Text)
      Mid$(m_sText, m_nPos, Len(Text)) = Text
      m_nPos = m_nPos + Len(Text)
      End Sub
      
      ' 添加一些文本字符串
      Public Sub Append(ParamArray Text())
      Dim nArg As Long
      For nArg = 0 To UBound(Text)
      AppendInternal CStr(Text(nArg))
      Next nArg
      End Sub
      
      ' 返回當前字符串數(shù)據(jù)并調整緩沖區(qū)大小
      Public Function ToString() As String
      If m_nPos > 0 Then
      Shrink
      ToString = m_sText
      Else
      ToString = ""
      End If
      End Function
      
      ' 清除緩沖區(qū)并重新初始化
      Public Sub Clear()
      InitBuffer
      End Sub
      
      此類中使用的基本原則是,在類級別將變量 (m_sText) 用作字符串緩沖區(qū),并使用 Space$ 函數(shù)以空格字符填充此緩沖區(qū)以將其設置為特定的大小。如果要將更多文本與現(xiàn)有文本連接在一起,則在檢查緩沖區(qū)的大小足以存放新文本后,使用 Mid$ 函數(shù)在正確位置插入文本。ToString 函數(shù)將返回當前存儲在緩沖區(qū)中的文本,并將緩沖區(qū)的大小調整為能夠容納此文本的正確長度。使用 StringBuilder 的 ASP 代碼如下所示:
      
      Function WriteHTML( Data )
      
      Dim oSB
      Dim nRep
      
      Set oSB = Server.CreateObject( "StringBuilderVB.StringBuilder" )
      ' 用大小和增長系數(shù)初始化緩沖區(qū)
      oSB.Init 15000, 7500
      
      For nRep = 0 to 99
      oSB.Append "<TR><TD>", (nRep + 1), "</TD><TD>", _
      Data( 0, nRep ), "</TD><TD>", _
      Data( 1, nRep ), "</TD><TD>", _
      Data( 2, nRep ), "</TD><TD>", _
      Data( 3, nRep ), "</TD><TD>", _
      Data( 4, nRep ), "</TD><TD>", _
      Data( 5, nRep ), "</TD></TR>"
      Next
      
      WriteHTML = oSB.ToString()
      Set oSB = Nothing
      
      End Function
      
      使用 StringBuilder 需要一定的開銷,因為每次使用此類時都必須創(chuàng)建它的實例,并且在創(chuàng)建第一個類實例時必須加載包含此類的 DLL。對 StringBuilder 實例進行額外方法調用時也需要開銷。使用加括號的“&”方法時,StringBuilder 如何執(zhí)行取決于多個因素,包括連接的數(shù)目、要構建的字符串的大小以及選擇的 StringBuilder 字符串緩沖區(qū)的初始化參數(shù)的性能。請注意,在多數(shù)情況下,將緩沖區(qū)中所需的空間量估計得略高一些要遠遠好于讓其不斷增長。
      
      內置方法
      
      ASP 包含一種非常快捷的創(chuàng)建 HTML 代碼的方法,只需多次調用 Response.Write。Write 函數(shù)使用隱式優(yōu)化的字符串緩沖區(qū),此緩沖區(qū)能夠提供非常優(yōu)秀的性能特性。修改后的 WriteHTML 代碼如下所示:
      
      Function WriteHTML( Data )
      
      Dim nRep
      
      For nRep = 0 to 99
      Response.Write "<TR><TD>"
      Response.Write (nRep + 1)
      Response.Write "</TD><TD>"
      Response.Write Data( 0, nRep )
      Response.Write "</TD><TD>"
      Response.Write Data( 1, nRep )
      Response.Write "</TD><TD>"
      Response.Write Data( 2, nRep )
      Response.Write "</TD><TD>"
      Response.Write Data( 3, nRep )
      Response.Write "</TD><TD>"
      Response.Write Data( 4, nRep )
      Response.Write "</TD><TD>"
      Response.Write Data( 5, nRep )
      Response.Write "</TD></TR>"
      Next
      
      End Function
      
      雖然這段代碼很可能為我們提供最佳的性能和可縮放性,但在某種程度上已經破壞了封裝,因為現(xiàn)在會將函數(shù)內部的代碼直接寫入 Response 流,所以調用代碼喪失了一定程度的控制權。另外,移動此代碼(例如,移入 COM 組件)將變得更加困難,因為此函數(shù)與 Response 流存在依賴關系。
      
      測試
      
      上面提到的四種方法分別通過一個簡單的 ASP 頁面(包含一個由虛擬字符串數(shù)組提供數(shù)據(jù)的單個表格)進行了測試。我們使用 Application Center Test? (ACT) 從單個客戶端(Windows? XP Professional,PIII-850MHz,512MB RAM)針對 100Mb/sec 網絡中的單個服務器(Windows 2000 Advanced Server,雙 PIII-1000MHz,256MB RAM)執(zhí)行了測試。ACT 配置為使用 5 個線程,以模擬 5 個用戶連接至網站時的負載。每個測試都包括 20 秒預熱時間和隨后的 100 秒負載時間,在負載期間創(chuàng)建了盡可能多的請求。
      
      通過更改主表格循環(huán)中的重復次數(shù),針對不同數(shù)目的連接操作重復運行測試,如 WriteHTML 函數(shù)中的代碼片斷所示。運行的每個測試都使用上文提到的四種不同的方法執(zhí)行。
      
      結果
      
      下面的一系列圖表顯示了各種方法對整個應用程序吞吐量的影響,以及 ASP 頁面的響應時間。通過這些圖表,我們可以了解應用程序支持的請求數(shù)目,以及用戶等待頁面下載至瀏覽器所需的時間。
      
      表 1:使用的連接方法縮寫的說明
      
     

      在模擬典型 ASP 應用程序工作負荷方面,此測試與實際情況相差甚遠,從表 2 中可以明顯看到,即使重復 420 次,此頁面仍不是特別大。現(xiàn)在很多復雜的 ASP 頁面在這些數(shù)字上都是比較高的,設置有可能超出此測試范圍的限制。
      
      表 2:測試示例的頁面大小和連接數(shù)目
      
     

      
     

      
    圖 2:吞吐量結果圖

      
      從圖 2 的圖表中可以看到,正如我們所預期的,多重 Response.Write 方法 (RESP) 在測試的整個重復測試范圍中為我們提供了最佳的吞吐量。但令人驚訝的是,標準字符串連接方法 (CAT) 的下降如此巨大,而加括號的方法 (PCAT) 在重復執(zhí)行 300 多次時性能依舊要好很多。在大約重復 220 次之處,字符串緩存帶來的性能提高超過了 StringBuilder 方法 (BLDR) 固有的開銷,在這一點以上,在此 ASP 頁面中使用 StringBuilder 所需的額外開銷是值得的。
      
     

      
    圖 3:響應時間結果圖

      

      
    圖 4:省略 CAT 的響應時間結果圖

      
      圖 3 和圖 4 中的圖表顯示了按“到第一字節(jié)的時間”測量的響應時間(以毫秒為單位)。因為標準字符串連接方法 (CAT) 的響應時間增加過快,所以又提供了未包括此方法的圖表(圖 4),以便分析其他方法之間的差異。有一點值得注意,多重 Response.Write 方法 (RESP) 和 StringBuilder 方法 (BLDR) 隨重復次數(shù)的增加呈現(xiàn)一種近似線性的增長,而標準連接方法 (CAT) 和加括號的方法 (PCAT) 則在超過一定的閾值之后開始迅速增加。
      
      小結
      
      本文著重講述了如何在 ASP 環(huán)境中應用不同的字符串構建技術,這些內容同樣適用于所有使用 Visual Basic 代碼創(chuàng)建大型字符串的方案,例如手動創(chuàng)建 XML 文檔。以下原則可以幫助您確定哪種方法最適合您的需要。
      
      首先嘗試加括號的“&”方法,尤其是在處理現(xiàn)有代碼時。這種方法對代碼結構的影響微乎其微,但您會發(fā)現(xiàn)應用程序的性能將顯著增強,甚至會超出預定目標。
      
      在不破壞所需的封裝級別的情況下使用 Response.Write。使用此方法,可以避免不必要的內存內字符串處理,從而提供最佳的性能。
      
      使用 StringBuilder 構建真正大型或連接數(shù)目較多的字符串。
      
      盡管您可能未看到本文所示的這種性能增長,但我已在真實的 ASP Web 應用程序中使用了這些技巧,只需要很少的額外投入就可以在性能和可縮放性方面獲得很大的提高。
    posted on 2010-06-10 11:33 Eric_jiang 閱讀(271) 評論(0)  編輯  收藏 所屬分類: ASP
    主站蜘蛛池模板: 亚洲最大在线视频| 亚洲国产精品成人| 国产91免费在线观看| 日本xxxx色视频在线观看免费| 三年在线观看免费观看完整版中文 | 国产片AV片永久免费观看| 精品免费久久久久久久| 国产精品永久免费10000| 91黑丝国产线观看免费 | 色屁屁在线观看视频免费| 日韩国产精品亚洲а∨天堂免| 亚洲av中文无码字幕色不卡| 亚洲aⅴ无码专区在线观看| 朝桐光亚洲专区在线中文字幕 | 亚洲国产成人资源在线软件| 亚洲伊人久久大香线蕉啊| 一本色道久久88—综合亚洲精品| 亚洲色偷偷偷综合网| 午夜免费国产体验区免费的| 久久国产精品免费一区| 午夜精品一区二区三区免费视频| 91精品全国免费观看含羞草 | 精品无码国产污污污免费网站 | 18女人腿打开无遮掩免费| 亚洲日本在线免费观看| 好爽…又高潮了免费毛片| 四虎影视精品永久免费网站| 中文字幕精品亚洲无线码二区| 亚洲av无码国产精品夜色午夜| 亚洲午夜久久久久久尤物| 久久精品国产亚洲AV电影网| 免费福利资源站在线视频| 在线播放免费人成毛片乱码| 亚洲高清视频免费| 国产免费午夜a无码v视频| 亚洲区小说区激情区图片区| 亚洲成无码人在线观看| 免费的黄网站男人的天堂| 久9这里精品免费视频| 天天摸天天碰成人免费视频| 国产a v无码专区亚洲av|