纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

C# StringBuilder提高性能 提高C# StringBuilder操作性能优化的方法

编程宝库   2021-11-19 我要评论
想了解提高C# StringBuilder操作性能优化的方法的相关内容吗编程宝库在本文为您仔细讲解C# StringBuilder提高性能的相关知识和一些Code实例欢迎阅读和指正我们先划重点:C#,StringBuilder性能优化,C#,StringBuilder,C#,StringBuilder提高性能下面大家一起来学习吧。

本文探讨使用C# StringBuilder 的最佳实践用于减少内存分配提高字符串操作的性能。

在 .NET 中String 对象是不可改变的。每次使用 System.String 类中的方法之一时都要在内存中创建一个新的字符串对象这就需要为该新对象分配新的空间。

在需要对字符串执行重复修改的情况下与创建新的 String 对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象则可以使用 System.Text.StringBuilder 类。例如当在一个循环中将许多字符串连接在一起时使用 StringBuilder 类可以提升性能。

BenchmarkDotNet是一款强力的.NET性能基准测试库为每个被测试的方法提供了孤立的环境。使用BenchmarkDotnet, 程序员可以很容易的编写各种性能测试方法并可以避免许多常见的坑。

本篇文章中我们将利用 BenchmarkDotNet 为我们的 StringBuilder 操作进行基准测试。

要使用本篇文章提供的代码示例你的系统中应该安装有 Visual Studio 2019 或者以上版本。

1. 在Visual Studio中创建一个控制台应用程序项目

首先让我们在 Visual Studio中 创建一个 .NET Core 控制台应用程序项目。假设你的系统中已经安装了 Visual Studio 2019请按照下面的步骤创建一个新的 .NET Core 控制台应用程序项目。

  • 1. 启动 Visual Studio IDE。
  • 2. 点击 "创建新项目"。
  • 3. 在 "创建新项目 "窗口中从显示的模板列表中选择 "控制台应用程序(.NET核心)"。
  • 4. 点击 "下一步"。
  • 5. 在接下来显示的 "配置你的新项目 "窗口中指定新项目的名称和位置。
  • 6. 点击创建。

这将在 Visual Studio 2019 中创建一个新的 .NET Core 控制台应用程序项目。我们将在本文的后续章节中使用这个项目来处理 StringBuilder。

2. 安装 BenchmarkDotNet NuGet包

要使用 BenchmarkDotNet你必须安装 BenchmarkDotNet 软件包。你可以通过 Visual Studio 2019 IDE 内的 NuGet 软件包管理器或在 NuGet 软件包管理器控制台执行以下命令来完成。

Install-Package BenchmarkDotNet

3. 使用 StringBuilderCache 来减少分配

StringBuilderCache 是一个内部类在 .NET 和 .NET Core 中可用。每当你需要创建多个 StringBuilder 的实例时你可以使用 StringBuilderCache 来大大减少分配的成本。

StringBuilderCache 的工作原理是缓存一个 StringBuilder 实例然后在需要一个新的 StringBuilder 实例时重新使用它。这减少了分配因为你只需要在内存中拥有一个 StringBuilder 实例。

让我们用一些代码来说明这一点。在 Program.cs 文件中创建一个名为 StringBuilderBenchmarkDemo 的类。创建一个名为 AppendStringUsingStringBuilder 的方法代码如下。

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

上面的代码片段显示了如何使用 StringBuilder 对象来追加字符串。接下来创建一个名为 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 方法创建一个 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);
      }
}

你现在必须使用 BenchmarkRunner 类来指定初始起点。这是一种通知 BenchmarkDotNet 在指定的类上运行基准的方式。

用以下代码替换 Main 方法的默认源代码。

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

现在在 Release 模式下编译你的项目并在命令行使用以下命令运行基准测试。

dotnet run -p StringBuilderPerfDemo.csproj -c Release

下面说明了两种方法的性能差异。

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

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

String 对象是不可变的所以修改一个 String 对象需要创建一个新的 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 使用的内存明显较少。

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 方法的参数来追加字符串。

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

下图显示了这两种方法的基准测试结果。

6. 其他 StringBuilder 优化方法

StringBuilder 允许你设置容量以提高性能。如果你知道你要创建的字符串的大小你可以相应地设置初始容量以大大减少内存分配。

你还可以通过使用一个可重复使用的 StringBuilder 对象池来避免分配来提高 StringBuilder 的性能。

最后请注意由于 StringBuilderCache是一个内部类你需要将源代码粘贴到你的项目中才能使用它。回顾一下在C#中你只能在同一个程序集或库中使用一个内部类。

因此我们的程序文件不能仅仅通过引用 StringBuilderCache 所在的库来访问 StringBuilderCache 类。

这就是为什么我们把 StringBuilderCache 类的源代码复制到我们的程序文件中也就是Program.cs文件。

参考资料:

1. C#教程

2. C#编程技术

3. 编程宝库

ASP.NET提高StringBuilder类操作性能就向你介绍到这里希望对你有所帮助。


相关文章

猜您喜欢

  • Vue router路由 详解Vue router路由

    想了解详解Vue router路由的相关内容吗维生素D没有用在本文为您仔细讲解Vue router路由的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Vue详解,Vue,router,router路由下面大家一起来学习吧。..
  • python时间序列calendar模块 python编程开发时间序列calendar模块示例详解

    想了解python编程开发时间序列calendar模块示例详解的相关内容吗Python学习与数据挖掘在本文为您仔细讲解python时间序列calendar模块的相关知识和一些Code实例欢迎阅读和指正我们先划重点:python编程开发,python时间序列calendar模块下面大家一起来学习吧。..

网友评论

Copyright 2020 www.tdogsoftware.com 【零度软件园】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式