Frage

Wie schnell kann ich Zeichen in einer Zeichenfolge ersetzen?

So ist der Hintergrund dieser Frage ist diese: Wir haben ein paar Anwendungen, die miteinander und mit Kunden Anwendungen über Sockets kommunizieren. Diese Socket-Nachrichten enthalten nicht druckbare Zeichen (zB chr (0)), die mit einer vorbestimmten Zeichenfolge ersetzt bekommen muß (zB „{Nul}“}, da die Socket-Nachrichten in einer Log-Datei gespeichert werden. Auf einer Seite zur Kenntnis, nicht jede Protokollmeldung müssen Zeichen haben ersetzt.

Nun begann ich auf dieses kleine Abenteuer Lesen von dieser MSDN Link , die ich von einem anderen Beitrag von dieser Seite gefunden.

Die aktuelle Methode verwendeten wir ... am Anfang des Tages ... wurde mit String für alle möglichen Alternativen zu prüfen, wie ...

    Public Function ReplaceSB(ByVal p_Message As String) As String
      Dim sb As New System.Text.StringBuilder(p_Message)

      sb.Replace(Chr(0), "{NUL}")
      sb.Replace(Chr(1), "{SOH}")

      Return sb.ToString
    End Function

Jetzt als Blog-Post weist darauf hin verlassen Stringbuilder und mit string.replace tut Ausbeute schnellere Ergebnisse. (Eigentlich String Verwendung war die langsamste Methode, dies den ganzen Tag lang zu tun.)

    p_Message = p_Message.Replace(Chr(0), "{NUL}")
    p_Message = p_Message.Replace(Chr(1), "{SOH}")

Das Wissen, dass nicht jede Nachricht durch diesen Prozess gehen müsste ich dachte, es Zeit sparen würde nicht diese Nachrichten verarbeiten müssen, die weggelassen werden könnte. Ich suchte zuerst die Zeichenfolge so mit regulären Ausdrücken und dann bestimmt, wenn sie verarbeitet werden müssen oder nicht. Das war ungefähr die gleiche wie die string.replace verwenden, im Grunde eine Wäsche von Speichern, die Zeit nicht alle die Saiten der Verarbeitung, aber von der Überprüfung sich alle mit regulären Ausdrücken zu verlieren Zeit.

Dann wurde vorgeschlagen, zu versuchen, einige Arrays, dass ihre Indizes mit den alten und den neuen und dem Einsatz abgestimmt, dass die Nachrichten zu verarbeiten. So wäre es so etwas wie dieses ...

Private chrArray() As Char = {Chr(0), Chr(1)}
Private strArray() As String = {"{NUL}", "{SOH}"}

Public Function TestReplace(ByVal p_Message As String) As String
    Dim i As Integer

    For i = 0 To ((chrArray.Length) - 1)
        If p_Message.Contains(chrArray(i).ToString) Then
            p_Message = p_Message.Replace(chrArray(i), strArray(i))
        End If
    Next

    Return p_Message
End Function

Das bisher der schnellste Weg, die ich gefunden habe, diese Nachrichten zu verarbeiten. Ich habe verschiedene andere Weise versucht der ebenso wie die Umwandlung der eingehenden Zeichenfolge in ein Zeichenarray über diese gehen und den Vergleich zusammen mit auch eher eine Schleife durch die Zeichenfolge versuchen, als die ChrArray.

Also meine Frage an alle ist: Kann ich diese noch schneller zu machen? Was bin ich?

War es hilfreich?

Lösung

Das könnte Sie der Lage sein, ein wenig mehr Geschwindigkeit zu verdrängen, indem sie einige Lookups reduzieren. Nehmen Sie zum Beispiel dieses:

    If p_Message.Contains(chrArray(i).ToString) Then

Die .Contains Methode ist O (n). Im schlimmsten Fall, Sie gehen alle die Zeichen in der gesamten Zeichenfolge zu durchqueren, ohne etwas zu finden, so dass Sie mindestens einmal für jedes Zeichen in Ihrem Array zu durchqueren erwarten, so dass ihr O (nm), wobei n die Länge Ihr String und m ist die Anzahl der Zeichen Sie ersetzen.

Sie könnte ein wenig bessere Leistung bekommen Sie wie folgt vorgehen (mein VB-fu rostig ist, wurde nicht geprüft;)):

Private Function WriteToCharList(s as String, dest as List(Of Char))
    for each c as Char in s
        dest.Add(c)
    Next
End Function

Public Function TestReplace(ByVal p_Message As String) As String
    Dim chars as new List(Of Char)(p_Message.Length)

    For each c as Char in p_Message
        Select Case c
            Case Chr(0): WriteToCharList("{NUL}", chars)
            Case Chr(1): WriteToCharList("{SOH}", chars)
            Case Else: chars.Add(c);
        End Select
    Next

    Return New String(chars)
End Function

Dies wird durchqueren Zeichen in p_Message höchstens zweimal (einmal für Verfahrweg, einmal, wenn die Zeichenfolge Konstruktor kopiert der char-Array), so dass diese Funktion O (n).

Andere Tipps

Dies sollte auch schneller:

    Private Shared strList As New Dictionary(Of Char, String)

    Shared Sub New()
        strList.Add(Chr(0), "{NUL}")
        strList.Add(Chr(1), "{SOH}")
    End Sub

    Public Function TestReplace(ByVal p_Message As String) As String
        For Each c As Char In strList.Keys
            If p_Message.IndexOf(c) <> -1 Then
                p_Message = p_Message.Replace(c, strList(c))
            End If
        Next

        Return p_Message
    End Function

StringBuilder bietet die schnellste Replace () Funktion in .NET.

Ein paar allgemeine Hinweise hier:

  1. Sie könnten in der Lage sein, auf die Suchfunktion zu verbessern, indem sie eine einfache .IndexOf() oder .Contains() Suche verwenden, da Sie nur sind für einzelne Zeichen suchen.
  2. Möglicherweise können Sie Ihren Gesamtdurchsatz verbessern, indem das Stringbuilder-Objekts aus Ihrer Funktion direkt Rückkehr und Überlastungen für andere Funktionen bereitstellt, die Stringbuilders als Eingabe oder Aufruf .ToString () irgendwo später im Prozess (Anmerkung akzeptieren: Sie können auch rufen .ToString () auf Objekte, die bereits Strings)
  3. Sie sollten definitiv in der Lage sein, die Leistung weiter zu verbessern / Durchsatz durch einen String / Textreader weiter oben in der Kette und solange als Strom zu behandeln alles, was die Kette bestand bis halten zu werden.

Am allerwenigsten können Sie Ihre endgültige Methode, um diese Art und Weise ändern:

Public Function TestReplace(ByVal p_Message As String) As String
    Static chrArray() As Char = {ChrW(0), ChrW(1)}
    Static strArray() As String = {"{NUL}", "{SOH}"}

    Dim rdr As New StringReader(p_Message)
    Dim result As New StringWriter()

    Dim i As Integer
    While (i = rdr.Read()) <> -1
        Dim c As Char = ChrW(i)
        Dim index As Integer = Array.IndexOf(chrArray, c)
        If index >= 0 Then result.Write(strArray(index)) Else result.Write(c)
    End While

    Return result.ToString()
End Function

Beachten Sie, dass Ihre Benchmarks stark von der Art der Saiten abhängen Sie sind Werfen es an, so stellen Sie sicher, dass Sie die meisten repräsentative Stichprobe mit (und es sollte eine gute Größe Probe sein) möglich.

Haben Sie einen Blick auf diese Beispiel . Es hat einige Benchmark-Statistiken Vergleich der beiden Methoden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top