【问题标题】:Finding faster ways to concatenate huge strings寻找连接大字符串的更快方法
【发布时间】:2012-04-23 12:01:24
【问题描述】:

我正在制作一个将图像转换为文本 RRR GGG BBB  字符串数组的应用程序。

它在处理小图像时非常快,但是当输入图像的像素数很高时,应用程序会逐渐变慢。

应用程序运行x,y 循环遍历输入图像的所有像素,扫描每个像素并将其 RGB 格式的值添加到最终字符串中,该字符串将在扫描整个图像后保存为文本。

在内置分析器的帮助下,我发现System.String.Concat(string,string) 花费的时间越长,最终字符串越大。

然后我尝试制作一个临时字符串,该字符串将保存 1 行的计算结果,并在输入下一行之前将其添加到最终字符串中。现在它的工作速度快了大约十倍,但仍然接近尾声,性能下降。

但最终我的所有测试图像都比真实图像要小。如何在更大的图像上保持较高的连接速度?

【问题讨论】:

  • 你如何处理字符串?您可以保存/发送其中的一部分吗?

标签: c# .net string-concatenation


【解决方案1】:

使用System.Text.StringBuilder:

var sb = new StringBuilder();
sb.Append(r);
sb.Append(g);
sb.Append(b);

string result = sb.ToString();

这个类是专门为快速字符串连接而设计的。我不知道有什么比它更快(对于一般情况)。

【讨论】:

  • 打开链接并向下滚动:)
  • 就是这样,现在它的工作速度更快了。巨大的图像处理速度也足够快。
  • 为了获得最佳性能,如果您大致知道所需的大小,请将其包含在构造函数中,例如new StringBuilder(sizeEstimate)。然后它会预先分配估计的大小,而不是从(可能小得多的)默认大小开始调整太多。
  • @我的最终字符串是否由等长的预格式化字符串组成,并且数字是垂直*水平图像尺寸,如果我在初始化时预先分配所需的确切空间,是否会有所改善? (在 16384*32 的图像中可能有大约 600 万个符号)
  • 是的,如果您可以轻松地预先计算出确切的尺寸,那就去吧!它还有助于避免内存碎片。快速测试显示速度提高了约 12% 以上,YMMV。
【解决方案2】:

详细说明@abatishchev 的回答:

当您连接字符串时,您实际上是在为每个连接创建一个新的字符串实例,因此您一直在分配数千(数百万?)个小字符串。 然而,StringBuilder 使用内部字符缓冲区来管理构建时的字符串,并避免这些频繁的分配。

用法是这样的:

StringBuilder sb = new StringBuilder();
foreach (Pixel pixel in myPixels)
{
    sb.Append(ConvertToString(pixel));
}

string myString = sb.ToString();

【讨论】:

    【解决方案3】:

    正如大家所说,是的,使用 StringBuilder。

    但是

    如果您已经有要以某种集合形式连接的字符串,String.Join() 被证明更快。

    请注意。

    【讨论】:

    • 根据 Reflector 的说法,考虑到它在内部使用 StringBuilder 的事实,如果 String.Join 更快,那将是令人惊讶的。编辑:罢工。似乎 Join 的一些重载使用了它们自己的不安全实现,而一些使用了 StringBuilder。很有趣。
    • 我对 string.Join 进行了更多研究,似乎如果你有一个现有的 array 字符串 (string[]),string.Join 将使用内部不安全的实施。但是,如果您有任何其他字符串集合(IEnumerable<string> 重载)或object[],则 string.Join 将在内部使用 StringBuilder。显然,当他们知道字符串在数组中按顺序排列时,他们可以挤压一些性能优势。
    • 有道理。无论哪种方式, string.Join 都只能改进。但当然,事先不在集合中 - StringBuilder 是要走的路。
    • 顺便说一句,你可以实现自己的 StringBuilder 比框架更有效。可以对框架 StringBuilder 进行一些改进,以提高性能,虽然我不记得细节了。
    【解决方案4】:

    使用String.Join("", myarray);

    【讨论】:

      【解决方案5】:

      像这样使用 StringBuilder:

      //add reference
      using System.Text
      
      //create string builder
      StringBuilder sb = new StringBuilder();
      //add items to it
      sb.Append("some text");
      sb.Append(" more text");
      

      【讨论】:

        【解决方案6】:

        StringBuilder 旨在处理庞大而复杂的字符串。

        【讨论】:

          猜你喜欢
          • 2012-02-04
          • 2011-08-04
          • 1970-01-01
          • 2020-02-20
          • 2020-12-18
          • 2011-02-23
          • 2011-04-24
          • 1970-01-01
          • 2021-07-09
          相关资源
          最近更新 更多