Ich hab es ja schon oft gehört und gelesen, dass mit Strings vorsichtig sein soll, wenn es um das Thema Performance geht, aber ich muss ehrlich zugeben, dass ich da nie sonderlich darauf achtgegeben habe, weil es hat ja alles funktioniert. Jetzt bin ich aber über einen Fall gestoßen, bei dem ich selbst nicht schlecht gestaunt habe, was ein einfacher String-Concat so alles anrichten kann.
Hier mal mein Beispiel:

Ich habe einen String mit Hexadezimalzahlen gegeben, der insgesamt 300 Zeichen lang ist:

4C-6F-72-65-6D-20-69-70-73-75-6D-20-64-6F-6C-6F-72-20-73-69-74-20-61-6D-65-74-2C-20-63-6F-6E-73-65-74-65-74-75-72-20-73-61-64-69-70-73-63-69-6E-67-20-65-6C-69-74-72-2C-20-73-65-64-20-64-69-61-6D-20-6E-6F-6E-75-6D-79-20-65-69-72-6D-6F-64-20-74-65-6D-70-6F-72-20-69-6E-76-69-64-75-6E-74-20-75-74-20-6C-61-62-6F-72-65-20-65-74-20-64-6F-6C-6F-72-65-20-6D-61-67-6E-61-2...

Der String soll jetzt als Block ausgegeben werden, wobei jeweils 16 Touple in einer Zeile stehen sollen.

Mein erster Versuch sah eigentlich ganz einfach aus:

    private string Block(string hex)
    {
        int size=47;
        int index = 0;

        string result = String.Empty;
        while (index < hex.Length)
        {
            if ((index + size) > hex.Length)
                result += hex.Substring(index) + Environment.NewLine;
            else
                result += hex.Substring(index, size) + Environment.NewLine;
            index += size + 1;
        }
        return result;
    }
  

Das Ganze funktionierte ganz gut. Dann ging es ans Testen mit echten Daten und der gegebene String war plötzlich 10.000 Zeichen lang und plötzlich lief das Programm gar nicht mehr flüssig.
Also hab ich gesucht, was der Grund dafür sein konnte. Die Daten kamen über einen Rest-Service und da gibt man natürlich erst einmal dem die Schuld, aber letztendlich hab ich den Fehler dann doch bei mir gefunden.
Ein einfacher Umbau der Block-Methode hat da wahre Wunder bewirkt:

    private string Block(string hex)
    {
        int size=47;
        int index = 0;

        StringBuilder result = new StringBuilder();
        while (index < hex.Length)
        {
            if ((index + size) > hex.Length)
	        result.AppendLine(hex.Substring(index));
            else
                result.AppendLine(hex.Substring(index, size));
            index += size + 1;
        }
	return result.ToString();
    }

Also wirklich nur die Änderung vom herkömmlichen String-Concat bzw + Operator zum StringBuilder Objekt. Auch bei großen Datenmengen konnte ich kaum eine Verzögerung bei der Block-Bildung feststellen.

Natürlich hab ich dann auch gleich einen kleinen Performance-Vergleich gemacht und diesen grafisch aufbereitet.
Ich habe dazu 50 Durchläufe jeweils gemacht, wobei jeder Durchlauf 1000 Zeichen mehr verarbeitet hat. Die linke Skala gibt die Anzahl der Ticks an, die dafür benötigt wurden.

Diagramm