Poprawianie wydajności łączenia ciągów za pomocą języka Visual C#

Ten artykuł zawiera informacje na temat zwiększania wydajności łączenia ciągów w języku Visual C#.

Oryginalna wersja produktu: Visual C#
Oryginalny numer KB: 306822

Podsumowanie

W tym artykule przedstawiono korzyści wynikające z używania klasy w StringBuilder stosunku do tradycyjnych technik łączenia. Ciągi w .NET Framework firmy Microsoft są niezmienne (tj. przywoływany tekst jest tylko do odczytu po początkowej alokacji). Zapewnia ona wiele korzyści z wydajności i stanowi pewne wyzwanie dla dewelopera, który jest przyzwyczajony do technik manipulowania ciągami C/C++.

Ten artykuł odnosi się do przestrzeni System.Textnazw biblioteki klas .NET Framework .

Opis ciągów w .NET Framework

Jedną z technik usprawniania łączenia ciągów w programie strcat() Visual C/C++ jest przydzielenie dużej tablicy znaków jako buforu i skopiowanie danych ciągu do buforu. W .NET Framework ciąg jest niezmienny i nie można go zmodyfikować. Operator łączenia języka C# + tworzy nowy ciąg i powoduje zmniejszenie wydajności podczas łączenia dużych ilości tekstu.

Jednak .NET Framework zawiera klasę zoptymalizowaną StringBuilder pod kątem łączenia ciągów. Zapewnia takie same korzyści jak użycie tablicy znaków w języku C/C++, a także automatyczne zwiększanie rozmiaru buforu (w razie potrzeby) i śledzenie długości. Przykładowa aplikacja w tym artykule przedstawia użycie StringBuilder klasy i porównuje wydajność z łączeniem.

Tworzenie i uruchamianie aplikacji demonstracyjnych

  1. Uruchom program Visual Studio, a następnie utwórz nową aplikację konsolową Visual C#.

  2. Poniższy kod używa += operatorów łączenia i StringBuilder klasy do czasu 5000 łączenia po 30 znaków. Dodaj ten kod do procedury głównej.

    const int sLen = 30, Loops = 5000;
    int i;
    string sSource = new String('X', sLen);
    string sDest = "";
    
    // Time string concatenation.
    var stopwatch = System.Diagnostics.Stopwatch.StartNew();
    for (i = 0; i < Loops; i++) sDest += sSource;
    stopwatch.Stop();
    Console.WriteLine($"Concatenation took {stopwatch.ElapsedMilliseconds} ms.");
    
    // Time StringBuilder.
    stopwatch.Restart();
    System.Text.StringBuilder sb = new System.Text.StringBuilder((int)(sLen * Loops * 1.1));
    for (i = 0; i < Loops; i++) 
        sb.Append(sSource);
    sDest = sb.ToString();
    stopwatch.Stop();
    Console.WriteLine($"String Builder took {stopwatch.ElapsedMilliseconds} ms.");
    
    // Make the console window stay open
    // so that you can see the results when running from the IDE.
    Console.WriteLine();
    Console.Write("Press Enter to finish ... ");
    Console.Read();
    
  3. Zapisz aplikację. Naciśnij klawisz F5, aby skompilować, a następnie uruchom aplikację. W oknach konsoli powinny być wyświetlane dane wyjściowe podobne do przykładów:

    Concatenation took 348 ms.
    String Builder took 0 ms.
    Press ENTER to finish...
    
  4. Naciśnij klawisz ENTER, aby zatrzymać uruchamianie aplikacji i zamknąć okno konsoli.

Rozwiązywanie problemów

  • Jeśli korzystasz ze środowiska, które obsługuje przesyłanie strumieniowe danych, na przykład w formularzu internetowym ASPX lub aplikacja zapisuje dane na dysku, rozważ uniknięcie narzutu buforu związanego z łączeniem lub StringBuilder, i zapisz dane bezpośrednio w strumieniu za pomocą Response.Write metody lub odpowiedniej metody dla danego strumienia.

  • Spróbuj ponownie użyć istniejącego StringBuilder class obiektu zamiast ponownego przydziału za każdym razem, gdy jest on potrzebny. Co ogranicza wzrost sterty i zmniejsza odzyskiwanie pamięci. W obu przypadkach użycie StringBuilder klasy sprawia, że sterta jest bardziej wydajna niż użycie + operatora.

Informacje

Klasa StringBuilder zawiera wiele innych metod manipulowania ciągami w miejscu, które nie zostały opisane w tym artykule. Aby uzyskać więcej informacji, wyszukaj StringBuilder w pomocy online.