熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

改進ASP程序中的字符串處理性能

2013-11-13 10:12:55  來源: .NET編程 

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

  
標准連接與加括號連接在內存使用模式方面的比較

  
  在特定情況下使用括號可以對性能和可縮放性產生十分顯著的影響後文將對此進行進一步的說明
  
  StringBuilder
  
  我們已經找到了解決字符串連接問題的快捷方法在多數情況下此方法可以達到性能和投入的最佳平衡但是如果要進一步提高構建大型字符串的性能需要采用第二種方法即減少字符串分配操作的數目為此需要使用 StringBuilderStringBuilder 是一個類用於維護可配置的字符串緩沖區管理插入到此緩沖區的新文本片斷並僅在文本長度超出字符串緩沖區長度時對字符串進行重新分配Microsoft NET 框架免費提供了這樣一個類 (SystemTextStringBuilder)並建議在該環境下進行的所有字符串連接操作中使用它在 ASP 和傳統的 Visual Basic 環境中我們無法訪問此類因此需要自行創建下面是使用 Visual Basic 創建的 StringBuilder 類示例(為簡潔起見省略了錯誤處理代碼)
  
  Option Explicit
  
   默認的緩沖區初始大小和增長系數
  Private Const DEF_INITIALSIZE As Long =
  Private Const DEF_GROWTH As Long =
  
   緩沖區大小和增長
  Private m_nInitialSize As Long
  Private m_nGrowth As Long
  
   緩沖區和緩沖區計數器
  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
   初始化緩沖區
  InitBuffer
  End Sub
  
   設置初始大小和增長數量
  Public Sub Init(ByVal InitialSize As Long ByVal Growth As Long)
  If InitialSize > Then m_nInitialSize = InitialSize
  If Growth > Then m_nGrowth = Growth
  End Sub
  
   初始化緩沖區
  Private Sub InitBuffer()
  m_nSize =
  m_nPos =
  End Sub
  
   增大緩沖區
  Private Sub Grow(Optional MinimimGrowth As Long)
   初始化緩沖區(如有必要)
  If m_nSize = 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
  
   將緩沖區大小調整到當前使用的大小
  Private Sub Shrink()
  If m_nSize > m_nPos Then
  m_nSize = m_nPos
  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 = To UBound(Text)
  AppendInternal CStr(Text(nArg))
  Next nArg
  End Sub
  
   返回當前字符串數據並調整緩沖區大小
  Public Function ToString() As String
  If m_nPos > Then
  Shrink
  ToString = m_sText
  Else
  ToString =
  End If
  End Function
  
   清除緩沖區並重新初始化
  Public Sub Clear()
  InitBuffer
  End Sub
  
  此類中使用的基本原則是在類級別將變量 (m_sText) 用作字符串緩沖區並使用 Space$ 函數以空格字符填充此緩沖區以將其設置為特定的大小如果要將更多文本與現有文本連接在一起則在檢查緩沖區的大小足以存放新文本後使用 Mid$ 函數在正確位置插入文本ToString 函數將返回當前存儲在緩沖區中的文本並將緩沖區的大小調整為能夠容納此文本的正確長度使用 StringBuilder 的 ASP 代
From:http://tw.wingwit.com/Article/program/net/201311/12940.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.