Frage

Ich habe mich gefragt, über String und ich habe eine Frage, die ich die Gemeinde hatte gehofft, wäre in der Lage zu erklären.

Lassen Sie sich nur über die Lesbarkeit des Codes vergessen, die von diesen ist schneller und warum?

StringBuilder.Append:

StringBuilder sb = new StringBuilder();
sb.Append(string1);
sb.Append("----");
sb.Append(string2);

StringBuilder.AppendFormat:

StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}----{1}",string1,string2);
War es hilfreich?

Lösung

Es ist unmöglich zu sagen, nicht die Größe von string1 und string2 zu kennen.

Mit dem Aufruf von AppendFormat , es wird der Puffer nur einmal angesichts der Länge des Formatstrings preallocate und die Saiten, die eingefügt werden und dann alles verketten und sie in den Puffer ein. Für sehr große Strings, wird dies über getrennte Anrufe von Vorteil sein, Append , die der Puffer mehrmals erweitern verursachen könnte.

Allerdings sind die drei Anrufe Append möglicherweise oder möglicherweise nicht das Wachstum des Puffers auslösen und dass der Check wird bei jedem Aufruf ausgeführt. Wenn die Saiten klein genug und kein Puffer Expansion sind ausgelöst wird, dann wird es schneller als der Aufruf AppendFormat, weil es nicht den Format-String analysieren müssen, um herauszufinden, wo die Ersetzungen zu tun.

Mehr Daten für eine endgültige Antwort erforderlich

Es ist zu beachten, dass es wenig Diskussion über die statischen mit Concat Methode auf der String Klasse ( Jon Antwort mit AppendWithCapacity erinnerte mich an diese). Seine Testergebnisse zeigen, dass der beste Fall zu sein (vorausgesetzt, Sie nicht nutzen spezifischen Formatbezeichner nehmen). String.Concat tut dasselbe, dass es die Länge der Saiten vorbestimmen verketten und preallocate den Puffer (mit etwas mehr Aufwand aufgrund von Konstrukten durch die Parameter Looping). Es ist die Leistung zu Jons AppendWithCapacity Methode vergleichbar sein wird.

Oder nur der einfache Additionsoperator, da es zu einem Aufruf kompiliert sowieso String.Concat, mit dem Vorbehalt, dass alle der Ergänzungen im selben Ausdruck sind:

// One call to String.Concat.
string result = a + b + c;

nicht

// Two calls to String.Concat.
string result = a + b;
result = result + c;

Für alle Testcode Aufstellen

Sie benötigen eine Testfälle in getrennt laufen läuft (oder zumindest, führen Sie eine GC zwischen dem Mess separater Testläufe). Der Grund dafür ist, dass, wenn Sie sagen, 1.000.000 läuft, einen neuen

Andere Tipps

casperOne korrekt . Sobald Sie eine bestimmte Schwelle erreicht, wird die Append() Methode langsamer als AppendFormat(). Hier sind die verschiedenen Längen und verstrichene Ticks von 100.000 Iterationen jeder Methode:

Länge: 1

Append()       - 50900
AppendFormat() - 126826

Länge: 1000

Append()       - 1241938
AppendFormat() - 1337396

Länge: 10.000

Append()       - 12482051
AppendFormat() - 12740862

Länge: 20.000

Append()       - 61029875
AppendFormat() - 60483914

Wenn Strings mit einer Länge in der Nähe von 20.000 eingeführt werden, die AppendFormat() Funktion wird leicht outperform Append().

Warum geschieht das? Siehe casperOne Antwort .

Edit:

reran ich jeden Test einzeln unter Release-Konfiguration und die Ergebnisse aktualisiert.

casperOne sind ganz genau, dass es auf den Daten abhängt. Allerdings nehme an, Sie dies als eine Klassenbibliothek sind schriftlich für 3. Parteien zu konsumieren - was würden Sie verwenden

Eine Möglichkeit wäre, das Beste aus beiden Welten zu bekommen - herausfinden, wie viele Daten Sie gehen, um tatsächlich anzuhängen, und dann verwenden StringBuilder.EnsureCapacity um sicherzustellen, dass wir nur einen einzigen Puffer Größe ändern müssen.

Wenn ich nicht war zu obwohl die Mühe gemacht, würde ich Append x3 verwenden - es scheint, „eher“ schneller zu sein, als bei jedem Aufruf der String-Format-Token-Parsing ist klar machen Arbeit .

Beachten Sie, dass ich habe das BCL-Team für eine Art „Im Cache Formatierer“, fragte die wir mit einem Format-String erstellen könnte und dann wiederholt wiederverwenden. Es ist verrückt, dass der Rahmen jedes Mal, wenn das Format-String zu analysieren hat es verwendet wird.

EDIT: Okay, ich habe Johns Code etwas für Flexibilität bearbeitet und hinzugefügt, um eine „AppendWithCapacity“, die sich über die nötige Kapazität funktioniert. Hier sind die Ergebnisse für die verschiedenen Längen - für Länge 1 I 1.000.000 Iterationen verwendet wird; für alle anderen Längen verwendet I 100.000. (Dies war nur vernünftig Laufzeiten zu erhalten.) Alle Zeiten sind in Millis.

Leider Tabellen wirklich funktionieren nicht in SO. Die Längen waren 1, 1000, 10000, 20000

Die Zeiten:

  • Anfügen: 162, 475, 7997, 17970
  • AppendFormat: 392, 499, 8541, 18993
  • AppendWithCapacity: 139, 189, 1558, 3085

So wie es passiert ist, habe ich nie gesehen AppendFormat Anfügen schlagen -. Aber ich haben sehen AppendWithCapacity durch eine sehr beträchtliche Marge gewinnen

Hier ist der vollständige Code:

using System;
using System.Diagnostics;
using System.Text;

public class StringBuilderTest
{            
    static void Append(string string1, string string2)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(string1);
        sb.Append("----");
        sb.Append(string2);
    }

    static void AppendWithCapacity(string string1, string string2)
    {
        int capacity = string1.Length + string2.Length + 4;
        StringBuilder sb = new StringBuilder(capacity);
        sb.Append(string1);
        sb.Append("----");
        sb.Append(string2);
    }

    static void AppendFormat(string string1, string string2)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendFormat("{0}----{1}", string1, string2);
    }

    static void Main(string[] args)
    {
        int size = int.Parse(args[0]);
        int iterations = int.Parse(args[1]);
        string method = args[2];

        Action<string,string> action;
        switch (method)
        {
            case "Append": action = Append; break;
            case "AppendWithCapacity": action = AppendWithCapacity; break;
            case "AppendFormat": action = AppendFormat; break;
            default: throw new ArgumentException();
        }

        string string1 = new string('x', size);
        string string2 = new string('y', size);

        // Make sure it's JITted
        action(string1, string2);
        GC.Collect();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < iterations; i++)
        {
            action(string1, string2);
        }
        sw.Stop();
        Console.WriteLine("Time: {0}ms", (int) sw.ElapsedMilliseconds);
    }
}

Append wird schneller in den meisten Fällen, weil es viele Überlastungen zu dieser Methode, die der Compiler aufrufen, die richtige Methode ermöglichen. Da Sie Strings die StringBuilder können verwenden die String Überlastung für Append verwenden.

AppendFormat nimmt einen String und ein Object[] dann, was bedeutet, dass das Format analysiert werden muß und jeder Object in dem Array werden ToString'd werden müssen, bevor sie den StringBuilder's internen Array hinzugefügt werden können.

Hinweis: Um casperOne des Punkt - es ist schwierig, eine genaue Antwort, ohne dass mehr Daten zu geben

.

StringBuilder hat auch kaskadiert Appends: Append() gibt den StringBuilder selbst, so können Sie Ihren Code wie folgt schreiben:

StringBuilder sb = new StringBuilder();
sb.Append(string1)
  .Append("----")
  .Append(string2);

Sauber und erzeugt weniger IL-Code (obwohl, das ist wirklich eine Mikro-Optimierung).

Natürlich Profil jeweils um sicher zu wissen.

Das heißt, ich denke, im Allgemeinen wird es die früheren sein, weil Sie die Formatzeichenfolge nicht wiederholt parsen.

Allerdings wäre der Unterschied sehr klein. Bis zu dem Punkt, dass Sie wirklich sollte auf jeden Fall mit AppendFormat in den meisten Fällen in Betracht ziehen.

Ich würde davon ausgehen, es war der Anruf, der die geringste Menge an Arbeit getan hat. Anfügen verkettet nur Strings, wobei AppendFormat wird Zeichenfolge Ersetzungen zu tun. Natürlich in diesen Tagen, kann man nie sagen ...

1 sollte schneller sein, weil es einfach ist die Saiten angehängt, während 2 eine Zeichenfolge auf einem Format basiert erstellen hat und dann die Zeichenfolge anhängen. So gibt es einen zusätzlichen Schritt in es.

Schneller ist 1 in Ihrem Fall jedoch es kein fairer Vergleich ist. Sie sollten fragen StringBuilder.AppendFormat () vs StringBuilder.Append (string.Format ().) - wo der erste ist schneller aufgrund interner Arbeits mit char-Array

Die zweite Möglichkeit ist aber mehr lesbar.

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