Kleine Ursache mit großen Auswirkungen

Dies hier ist ein kleiner Nachklapp zum Optimierungs-Artikel, und ich möchte Ihnen hiermit in aller Kürze erklären, wie Sie das String- oder Texthandling mit minimalem Aufwand extrem beschleunigen können.

Sie wissen ja: Ich benutze bevorzugt das Xojo-Framework, um spätere Anpassungen, wenn es zum Standard auf den Nicht-iOS-Plattformen geworden ist, so einfach wie möglich zu halten. Die Textklasse, die den althergebrachten String ersetzt, ist naturgemäß etwas langsamer, weil sie stets ein Textencoding mit sich führt und nicht mehr so einfach Byte = Zeichen gerechnet werden kann.

Im Forum finden sich denn auch Beschwerden über die damit einhergehenden Performance-Einbußen. Ja, der größere Komfort und die größere Sicherheit von Text gehen mit einem Geschwindigkeitsverlust einher. Tatsache ist aber: Sollten Sie Ihre Text- oder Stringvariablen auf eine Art zusammenschrauben wie:

Dim GesamtText as Text = Einführungstext + Haupttext + Abschlusstext + Referenzen

(oder eben auch mit String), dann haben Sie wirklich keinen Grund, sich zu beschweren, da Sie eine extrem langsame Funktion gewählt haben. Das Zusammensetzen von Textelementen (womit ich jetzt beide Klassen meine, Text und String) mittels „+“ ist extrem viel langsamer als der Join-Befehl.

Wieviel langsamer, das hat mich selbst überrascht. Da Probieren plattitüdenhalber den Wert des Studierens übersteigt: Schauen Sie sich doch einmal dieses Programm an. Sie können eine bestimmte Textelementlänge einstellen, die dann mit mehreren Methoden einen solchen Text zu einem großen Textelement verknüpft.

TextAppendScreen

Hier einmal das Ergebnis für eine Textlänge von 100 Zeichen, 10.000mal aneinandergehängt, aus einem Mac-Debugbuild.

Die Ergebnisse lesen sich wie folgt: Die Zahl ist die Ausführungszeit jeder Schleife in Nanosekunden. Text.Join habe ich zum Referenzwert erhoben, deshalb sehen Sie dort immer 100%. Und die Zeilen darunter die Ausführungszeiten und der prozentuale Vergleichswert.

Die Methoden sind (schematisch):

  • Text.Join: Dim Result As Text = Text.Join(TextArray, "")
  • Text.+: Dim Result As Text = Text1 + Text 2 + …
  • String.Join: Dim Result As String = Join(StringArray, "")
  • String.+: Dim Result As String = String1 + String2 + …
  • MemblockString benutzt den FastMemoryBlockString, der in der Xojo-Sprachreferenz als Methode zur schnellen Handhabung von großen String-Verknüpfungen empfohlen wird.

Je nachdem, welche Textelementlängen wie häufig verknüpft werden, variieren die Verhältnisse. Insgesamt ist bei beiden Textklassen der Join-Befehl aber um Welten schneller als ein +. Ich habe teilweise Faktoren von über 300 gemessen.

Und falls Sie den MemoryBlockString in Ihren Projekten verwenden, lautet mein Hinweis: Vergessen Sie ihn und benutzen Sie eine der Join-Methoden. Selbst mit Text sind Sie damit i.d.R. schneller.

Wenn Sie also häufiger einmal Text zusammensetzen (denken Sie z.B. an SQL-Befehle): Bauen Sie konsequent alles auf Join um, und Ihr Programm wird fliegen!

P.S.: Statt der Leerstring-Deklaration in den Join-Zeilen („“) empfiehlt es sich, eine leere Textelementkonstante zu verwenden. Das beschleunigt alles noch einmal erheblich.

P.P.S.: Dankenswerterweise erreichte mich schon ein sehr berechtigtes Feedback: Eine genaue Vergleichbarkeit wäre erst gegeben, wenn die Zeit zur Erstellung des Arrays mit berücksichtigt wird. Absolut richtig (wobei man in der Praxis auch bei „+“ häufig auf ein Array zurückgreifen dürfte), und wenn Sie ganz reale Vergleichswerte haben wollen, bauen Sie das Programm gerne einmal so um. Oder lassen Sie sich die Zeit der Array-Erstellung mit angeben. In der Praxis allerdings sind Xojo-Arrays sehr, sehr schnelle Konstrukte. Falls Sie ein Datenbankprojekt herumliegen haben, das ein SQL-Select mittels „+“ zusammenbaut: Machen Sie einmal ein Join daraus, ersetzen Sie die „+“ durch Kommas und packen Sie alle Strings oder Texte in eine Array()-Klammer. Testen Sie die Ausführungszeiten vorher und nachher: Der Unterschied wird immer noch sehr groß sein.

Die Erstellungzeit für String- und TextArrays gemeinsam liegt bei unter 3% des Referenzwerts, nebenbei. Bauen Sie den Anfang von PushButton1.Action einfach so um, um sich selbst zu überzeugen:

using xojo.core
dim appendtext() as string
dim appLength as integer = integer.parse (TextField2.text.ToText)
dim d as date = date.now
for q as integer = 1 to appLength
appendtext.Append chr(xojo.math.RandomInt(0,255))
next
dim st as string = join(appendtext, "")
dim dif as DateInterval = date.now - d
dim iterations as uint64 = uint64.Parse(TextField1.Text.ToText)

TextArea1.AppendText „Stringlength „+st.Len.ToText+“, „+iterations.ToText+“ Appends“+EndOfLine
TextArea1.AppendText dif.NanoSeconds.ToText+“ Time to create Arrays „+EndOfLine+EndOfLine

dim t aS text = st.ToText
dim result, empty as text
dim arr() as text
d = date.now
for q as uint64 = 1 to iterations
arr.Append t
next
result = text.Join (arr, empty)

dif = date.now – d
TextArea1.AppendText dif.NanoSeconds.ToText+“ Text.Join (100 %) „+EndOfLine
app.DoEvents 5

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s