溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#提高StringBuilder操作性能優(yōu)化的方法是什么

發(fā)布時間:2021-11-20 08:50:26 來源:億速云 閱讀:172 作者:iii 欄目:開發(fā)技術

本篇內(nèi)容介紹了“C#提高StringBuilder操作性能優(yōu)化的方法是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

在 .NET 中,String 對象是不可改變的。每次使用 System.String 類中的方法之一時,都要在內(nèi)存中創(chuàng)建一個新的字符串對象,這就需要為該新對象分配新的空間。

在需要對字符串執(zhí)行重復修改的情況下,與創(chuàng)建新的 String 對象相關的系統(tǒng)開銷可能會非常昂貴。如果要修改字符串而不創(chuàng)建新的對象,則可以使用 System.Text.StringBuilder 類。例如,當在一個循環(huán)中將許多字符串連接在一起時,使用 StringBuilder 類可以提升性能。

BenchmarkDotNet是一款強力的.NET性能基準測試庫,為每個被測試的方法提供了孤立的環(huán)境。使用BenchmarkDotnet, 程序員可以很容易的編寫各種性能測試方法,并可以避免許多常見的坑。

本篇文章中,我們將利用 BenchmarkDotNet 為我們的 StringBuilder 操作進行基準測試。

要使用本篇文章提供的代碼示例,你的系統(tǒng)中應該安裝有 Visual Studio 2019 或者以上版本。

1. 在Visual Studio中創(chuàng)建一個控制臺應用程序項目

首先讓我們在 Visual Studio中 創(chuàng)建一個 .NET Core 控制臺應用程序項目。假設你的系統(tǒng)中已經(jīng)安裝了 Visual Studio 2019,請按照下面的步驟創(chuàng)建一個新的 .NET Core 控制臺應用程序項目。

  • 1. 啟動 Visual Studio IDE。

  • 2. 點擊 "創(chuàng)建新項目"。

  • 3. 在 "創(chuàng)建新項目 "窗口中,從顯示的模板列表中選擇 "控制臺應用程序(.NET核心)"。

  • 4. 點擊 "下一步"。

  • 5. 在接下來顯示的 "配置你的新項目 "窗口中,指定新項目的名稱和位置。

  • 6. 點擊創(chuàng)建。

這將在 Visual Studio 2019 中創(chuàng)建一個新的 .NET Core 控制臺應用程序項目。我們將在本文的后續(xù)章節(jié)中使用這個項目來處理 StringBuilder。

2. 安裝 BenchmarkDotNet NuGet包

要使用 BenchmarkDotNet,你必須安裝 BenchmarkDotNet 軟件包。你可以通過 Visual Studio 2019 IDE 內(nèi)的 NuGet 軟件包管理器,或在 NuGet 軟件包管理器控制臺執(zhí)行以下命令來完成。

Install-Package BenchmarkDotNet

3. 使用 StringBuilderCache 來減少分配

StringBuilderCache 是一個內(nèi)部類,在 .NET 和 .NET Core 中可用。每當你需要創(chuàng)建多個 StringBuilder 的實例時,你可以使用 StringBuilderCache 來大大減少分配的成本。

StringBuilderCache 的工作原理是緩存一個 StringBuilder 實例,然后在需要一個新的 StringBuilder 實例時重新使用它。這減少了分配,因為你只需要在內(nèi)存中擁有一個 StringBuilder 實例。

讓我們用一些代碼來說明這一點。在 Program.cs 文件中創(chuàng)建一個名為 StringBuilderBenchmarkDemo 的類。創(chuàng)建一個名為 AppendStringUsingStringBuilder 的方法,代碼如下。

public string AppendStringUsingStringBuilder()
{
    var stringBuilder = new StringBuilder();
    stringBuilder.Append("First String");
    stringBuilder.Append("Second String");
    stringBuilder.Append("Third String");
    return stringBuilder.ToString();
}

上面的代碼片段顯示了如何使用 StringBuilder 對象來追加字符串。接下來創(chuàng)建一個名為 AppendStringUsingStringBuilderCache 的方法,代碼如下。

public string AppendStringUsingStringBuilderCache()
{
    var stringBuilder = StringBuilderCache.Acquire();
    stringBuilder.Append("First String");
    stringBuilder.Append("Second String");
    stringBuilder.Append("Third String");
    return StringBuilderCache.GetStringAndRelease(stringBuilder);
}

上面的代碼片段說明了如何使用 StringBuilderCache 類的 Acquire 方法創(chuàng)建一個 StringBuilder 實例,然后用它來追加字符串。

下面是 StringBuilderBenchmarkDemo 類的完整源代碼供你參考。

[MemoryDiagnoser]
public class StringBuilderBenchmarkDemo { [Benchmark]
      public string AppendStringUsingStringBuilder() {
            var stringBuilder = new StringBuilder();
            stringBuilder.Append("First String");
            stringBuilder.Append("Second String");
            stringBuilder.Append("Third String");
            return stringBuilder.ToString();
      }
      [Benchmark]
      public string AppendStringUsingStringBuilderCache() {
            var stringBuilder = StringBuilderCache.Acquire();
            stringBuilder.Append("First String");
            stringBuilder.Append("Second String");
            stringBuilder.Append("Third String");
            return StringBuilderCache.GetStringAndRelease(stringBuilder);
      }
}

你現(xiàn)在必須使用 BenchmarkRunner 類來指定初始起點。這是一種通知 BenchmarkDotNet 在指定的類上運行基準的方式。

用以下代碼替換 Main 方法的默認源代碼。

static void Main(string[] args)
{
    var summary = BenchmarkRunner.Run<StringBuilderBenchmarkDemo>();
}

現(xiàn)在在 Release 模式下編譯你的項目,并在命令行使用以下命令運行基準測試。

dotnet run -p StringBuilderPerfDemo.csproj -c Release

下面說明了兩種方法的性能差異。

C#提高StringBuilder操作性能優(yōu)化的方法是什么

正如你所看到的,使用 StringBuilderCache 追加字符串要快得多,需要的分配也少。

4. 使用 StringBuilder.AppendJoin 而不是 String.Join

String 對象是不可變的,所以修改一個 String 對象需要創(chuàng)建一個新的 String 對象。因此,在連接字符串時,你應該使用 StringBuilder.AppendJoin 方法,而不是String.Join,以減少分配,提高性能。

下面的代碼列表說明了如何使用 String.Join 和 StringBuilder.AppendJoin 方法來組裝一個長字符串。

[Benchmark]
public string UsingStringJoin() {
            var list = new List < string > {
                        "A",
                        "B", "C", "D", "E"
            };
            var stringBuilder = new StringBuilder();
            for (int i = 0; i < 10000; i++) {
                        stringBuilder.Append(string.Join(' ', list));
            }
            return stringBuilder.ToString();
}
[Benchmark]
public string UsingAppendJoin() {
            var list = new List < string > {
                        "A",
                        "B", "C", "D", "E"
            };
            var stringBuilder = new StringBuilder();
            for (int i = 0; i < 10000; i++) {
                        stringBuilder.AppendJoin(' ', list);
            }
            return stringBuilder.ToString();
}

下圖顯示了這兩種方法的基準測試結果。

請注意,對于這個操作,這兩種方法的速度很接近,但 StringBuilder.AppendJoin 使用的內(nèi)存明顯較少。

C#提高StringBuilder操作性能優(yōu)化的方法是什么

5. 使用 StringBuilder 追加單個字符

注意,在使用 StringBuilder 時,如果需要追加單個字符,應該使用 Append(char) 而不是 Append(String)。

請考慮以下兩個方法。

[Benchmark]
public string AppendStringUsingString() {
      var stringBuilder = new StringBuilder();
      for (int i = 0; i < 1000; i++) {
            stringBuilder.Append("a");
            stringBuilder.Append("b");
            stringBuilder.Append("c");
      }
      return stringBuilder.ToString();
}
[Benchmark]
public string AppendStringUsingChar() {
      var stringBuilder = new StringBuilder();
      for (int i = 0; i < 1000; i++) {
            stringBuilder.Append('a');
            stringBuilder.Append('b');
            stringBuilder.Append('c');
      }
      return stringBuilder.ToString();
}

從名字中就可以看出,AppendStringUsingString 方法說明了如何使用一個字符串作為 Append 方法的參數(shù)來追加字符串。

AppendStringUsingChar 方法說明了你如何在 Append 方法中使用字符來追加字符。

下圖顯示了這兩種方法的基準測試結果。

C#提高StringBuilder操作性能優(yōu)化的方法是什么

6. 其他 StringBuilder 優(yōu)化方法

StringBuilder 允許你設置容量以提高性能。如果你知道你要創(chuàng)建的字符串的大小,你可以相應地設置初始容量以大大減少內(nèi)存分配。

你還可以通過使用一個可重復使用的 StringBuilder 對象池來避免分配來提高 StringBuilder 的性能。

最后,請注意,由于 StringBuilderCache是一個內(nèi)部類,你需要將源代碼粘貼到你的項目中才能使用它?;仡櫼幌?,在C#中你只能在同一個程序集或庫中使用一個內(nèi)部類。

因此,我們的程序文件不能僅僅通過引用 StringBuilderCache 所在的庫來訪問 StringBuilderCache 類。

這就是為什么我們把 StringBuilderCache 類的源代碼復制到我們的程序文件中,也就是Program.cs文件。

“C#提高StringBuilder操作性能優(yōu)化的方法是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI