當串連大型字串 50 KB 的順序或更大 (例如,建置 HTML 表格從資料庫) 的要完成的時間長度可能會變得很長如字串取得較大。本文將告訴您,可以改善效能由大型字串,20 次] 或 [多的標準串連的替代方案。
執行的型別重複的串連時:
For I = 1 To N
Dest = Dest & Source
Next N
按比例為 N 平方的時間長度會增加。因此,1000年反覆項目將會採取大約 100 次長度超過 100 次反覆運算。這是因為 Visual Basic 不只是將來源字元加入目的地字串的結尾 ; 它也會執行下列作業:
- 配置暫存記憶體不夠大,無法存放結果。
- 將目的地複製到暫存區的開頭。
- 複製來源],以暫存區的結尾。
- de-allocates 舊複本的目的地。
- 會配置的記憶體不夠大,無法保存結果的目的地。
- 將暫存資料複製到目的地。
步驟 2 和 6 都非常昂貴,且基本上產生兩次與配置及解除配置記憶體的額外負荷正在複製整個串連結果。
本文件詳細說明一個方法使用 Mid $ 陳述式和 pre-allocating 以步驟 3 上述以外的所有消除大部份的 「 串連 」 階段的較大的區塊 (Chunk) 中的記憶體。
警告: 任何使用您程式碼本文中所提供的是,請自行負擔相關的風險。Microsoft 提供 「 現狀 」 這個程式碼並不提供任何種類明示或默示包括但不是限於適售性以及適合某特定用途之默示擔保責任。
雖說是逐步範例
- 下列程式碼輸入一個模組:
Option Explicit
' For 16-bit products, uncomment the next three lines by removing the
' single quotes and add a single quote to comment out the following
' three lines.
' Const ConcatStr = "ABC"
' Const ccIncrement = 15000
' Declare Function GetTickCount Lib "USER" () As Long
Const ConcatStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Const ccIncrement = 50000
Private Declare Function GetTickCount Lib "KERNEL32" () As Long
Dim ccOffset As Long
Sub StdConcat(ByVal LoopCount As Long)
Dim BigStr As String, I As Long, StartTick As Long
StartTick = GetTickCount()
For I = 1 To LoopCount
BigStr = BigStr & ConcatStr
Next I
Debug.Print LoopCount; "concatenations took";
Debug.Print GetTickCount() - StartTick; "ticks"
End Sub
Sub Test_Concat()
Debug.Print "Using standard concatenation"
StdConcat 1000
StdConcat 2000
StdConcat 3000
StdConcat 4000
StdConcat 5000
Debug.Print
Debug.Print "Using pre-allocated storage and pseudo-concatenation"
MidConcat 1000
MidConcat 2000
MidConcat 3000
MidConcat 4000
MidConcat 5000
End Sub
Sub Concat(Dest As String, Source As String)
Dim L As Long
L = Len(Source)
If (ccOffset + L) >= Len(Dest) Then
If L > ccIncrement Then
Dest = Dest & Space$(L)
Else
Dest = Dest & Space$(ccIncrement)
End If
End If
Mid$(Dest, ccOffset + 1, L) = Source
ccOffset = ccOffset + L
End Sub
Sub MidConcat(ByVal LoopCount As Long)
Dim BigStr As String, I As Long, StartTick As Long
StartTick = GetTickCount()
ccOffset = 0
For I = 1 To LoopCount
Concat BigStr, ConcatStr
Next I
BigStr = Left$(BigStr, ccOffset)
Debug.Print LoopCount; "pseudo-concatenations took";
Debug.Print GetTickCount() - StartTick; "ticks"
End Sub
- 在 [偵錯/即時運算] 視窗中輸入 Test_Concat,並按 Enter 鍵]。
結果會看起來類似:
Using standard concatenation
1000 concatenations took 2348 ticks
2000 concatenations took 8954 ticks
3000 concatenations took 20271 ticks
4000 concatenations took 35103 ticks
5000 concatenations took 54453 ticks
Using pre-allocated storage and pseudo-concatenation
1000 pseudo-concatenations took 82 ticks
2000 pseudo-concatenations took 124 ticks
3000 pseudo-concatenations took 165 ticks
4000 pseudo-concatenations took 247 ticks
5000 pseudo-concatenations took 289 ticks
其他資訊
- 程式碼可能要花幾分鐘才能執行。
- 啟動 Windows 後,GetTickCount 會傳回毫秒的數。因此,輸出是以毫秒為單位)。
- 效能改進範圍從幾乎 30 次的 1000年反覆項目大小寫以幾乎 200 次為 5000 反覆項目的案例。這些時間可能會視而異:
- 使用產品。
- 您的系統設定
- ccIncrement 大小 (較大的大小會偏重 MidConcat)。
- 使用的反覆運算次數 (多個反覆項目會偏重 MidConcat)。
- (較大的大小會偏重 MidConcat) 的結果字串的大小。
如需詳細資訊按一下 [下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項]:
306821?
(http://support.microsoft.com/kb/306821/EN-US/
)
如何改善 Visual Basic.NET 中的字串串連效能