vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Top-Preis! AP-Access-Tools-CD Volume 1  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Variablen/Strings · String-Operationen   |   VB-Versionen: VB4, VB5, VB628.06.04
Stringverkettung optimiert

Dieser "Klasse"-Tipp zeigt, wie sich das Anfügen von Text an einen bestehenden String um ein Vielfaches optimieren lässt.

Autor:   Roland OrtegaBewertung:     [ Jetzt bewerten ]Views:  17.088 
ohne HomepageSystem:  Win9x, WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11 Beispielprojekt auf CD 

Zur Aufgabe / zum Problem:
Es soll eine Datenübertragung zwischen zwei PCs über das Winsock-Control realisiert werden (identische Verhältnisse hat man bspw. auch beim asynchronen Download per Inet-Control, wenn man z.B. eine eigene Fortschrittsanzeige haben möchte). Das Problem dabei ist, dass die Daten "portionsweise" eintreffen und auf dem Zielrechner erst wieder zusammengesetzt werden müssen.

Natürlich geht das in VB ganz einfach:

Gesamtstring = Gesamtstring & Datenpaket

Bei etwas grösseren String, so im MB Bereich, dauerte das Ganze aber schier "unendlich" lange, so dass trotz eines 100 MBit lokalen Netzwerks kaum mehr ISDN Geschwindigkeit herauskommt.

Um die Stringverkettung zu optimieren, war der erste Gedanke: RTLMoveMemory-Funktion aus dem Windows API. Doch dann bin ich auf eine recht simple und mit reinen VB-Mitteln realisierbare Variante gestossen, die bei grossen Strings locker um den Faktor 1000 und mehr schneller ist.

Herausgekommen ist folgendes Klassenmodul:

Option Explicit
 
' private Variablen
Private sCollect As String
Private nLen As Long
Private sTemp  As String
Private Sub Class_Initialize()
  ' Sammelstring vor-initialisieren
  Reset
End Sub
Public Sub Reset()
  sCollect = String$(100, " ")
  nLen = 0
End Sub
Public Property Get Result() As String
  ' korrekter Rückgabe-String
  Result = Left$(sCollect, nLen)
End Property
Public Sub Add(sString As String)   
  If Len(sString) + nLen > Len(sCollect) Then
    ' Es ist wichtig für die Performance, dass der String 
    ' immer verdoppelt wird, da ansonsten zu oft
    ' neuer Speicherplatz angefordert würde, was die 
    ' Performance wiederrum zunichte macht    
    sTemp = Left$(sCollect, nLen)
    sCollect = String$(2 * Len(sCollect) + Len(sString), " ")
    Mid$(sCollect, 1, nLen) = sTemp
    sTemp = "" ' damit der Speicher wieder frei wird !
  End If
 
  Mid$(sCollect, nLen + 1, Len(sString)) = sString
  nLen = nLen + Len(sString)
End Sub

Das Prinzip:
Bevor dem bestehenden String der neue String angefügt wird, wird der bestehende String bei Bedarf "verdoppelt", d.h. mit entsprechend Leerzeichen aufgefüllt, so dass sich die Stringlänge verdoppelt. Grund ist der, dass bei häugigen String-Anfügefunktionen nicht jedes Mal neuer Speicherplatz vom System angefordert werden muss! Der neue String wird dann einfach in den bestehenden (zu langen) String an der korrekten Position "eingefügt".

Ein kleines Beispielprojekt:
Starten Sie die VB-Entwicklungsumgebung und fügen dem Projekt ein neues Klassenmodul mit obigen Code hinzu. Platzieren Sie auf die Form1 zwei CommandButtons (Command1 und Command2). Beim Klick auf die CommandButtons soll 10000 mal das Alphabet (String mit 26 Buchstaben) zu einem bestehenden String hinzugefügt werden.

Option Explicit
 
Dim sAlphabet As String
Private Sub Form_Load()
  Dim i As Long
 
  sAlphabet = ""
  For i = 65 To 90
    sAlphabet = sAlphabet & Chr$(i)
  Next
End Sub
Private Sub Command1_Click()
  Dim nTime As Single
  Dim sResult As String
  Dim i As Long
 
  nTime = Timer
 
  ' ------------------------------------------------------------
  ' Simpel: Die Aufgabe lösen, indem an den späteren Zielstring 
  ' immer wieder der gewünschte String angehängt wird ...
 
  For i = 1 To 10000
    sResult = sResult & sAlphabet
  Next i
 
  MsgBox "Benötigte Zeit: " & _
    Format$(Int((Timer - nTime) * 1000), "#,###,##0 ms")
End Sub
Private Sub Command2_Click()
  Dim nTime As Single
  Dim sResult As String
  Dim i As Long
 
  nTime = Timer
 
  ' ------------------------------------------------------------
  ' die bessere Variante: Erst den Speicherplatz reservieren 
  ' und dann gezielt den String einbauen
 
  Dim oClass As New Class1
 
  For i = 1 To 10000
    oClass.Add sAlphabet
  Next i
 
  MsgBox "Benötigte Zeit: " & _
    Format$(Int((Timer - nTime) * 1000), "#,###,##0 ms")   
End Sub

Das Ergebnis:
Die erste Variante (VB-Standard-Stringverkettung) benötigte im Test 843 ms. Die zweite Variante, bei der der String über das Klassenmodul zusammengesetzt wurde, benötigte für das gleiche Resultat nur 14 ms!

Es kommt aber noch dicker: Verdoppeln Sie einmal den Durchlaufwert von 10000 auf 20000. Hier braucht die erste Variante dann schon sage und schreibe 16034 ms. Die zweite Variante hingegen erledigte die gleiche Aufgabe in hervorragenden 31 ms!!!
 

Dieser Tipp wurde bereits 17.088 mal aufgerufen.

Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

Über diesen Tipp im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
(einschl. Beispielprojekt!)

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel