什么是StringBuilder的RAM消耗?

问题描述:

我们有几个操作,我们正在做大量的大字符串连接,并且最近遇到了内存不足异常。不幸的是,调试代码不是一种选择,因为这发生在客户现场。因此,在查看代码大修之前,我想问一下:StringBuilder对于大型字符串的RAM消耗特性是什么?什么是StringBuilder的RAM消耗?

尤其是它们与标准字符串类型进行比较。字符串的大小超过了10 MB,我们似乎遇到了大约20 MB的问题。

备注:这不是关于速度,而是RAM。

这是一个很好的研究String Concatenation vs Memory Allocation

如果你可以避免连接,那就做吧!

这是没有道理的,如果你不 有来连接,但希望你 源代码好看,使用 第一种方法。如果它是单个字符串,它将被优化为 。

不要使用+ =连接。幕后发生了太多的变化 ,这些都不是我的代码中最明显的 。 I 建议使用String.Concat() 明确地使用任何过载(2 字符串,3个字符串,字符串数组)。 这将清楚地显示你的代码 没有任何意外,而 允许自己保持对 的效率检查。

尝试估计一个StringBuilder的目标大小。

更准确,你可以估算 需要的尺寸,更低临时 字符串的StringBuilder将不得不 创建,以增加其内部 缓冲区。

当性能出现问题时,不要使用任何Format()方法。

开销太大参与 解析格式,当你可以 构建阵列出件时 所有正在使用的是{X}取代。 格式()有助于提高可读性,但 当您使用 时,需要执行的操作之一是将应用程序的所有可能的性能提高到 。

每次StringBuilder用完空间时,它会重新分配一个新的缓冲区两倍于原始缓冲区的大小,复制旧的字符,并让旧的缓冲区得到GC'd。有可能你使用的足够多(称之为x),使得2x大于你允许分配的内存。您可能需要为您的字符串确定一个最大长度,并将其传递给StringBuilder的构造函数,以便预先分配,并且不受双倍重新分配的支配。

我不知道字符串生成器的确切内存模式,但常用的字符串不是一个选项。

当您使用公共字符串时,每个连接都会创建另一对字符串对象,并且内存消耗会飞涨,从而导致垃圾收集器被频繁调用。

string a = "a"; 

//creates object with a 

a += "b" 

/creates object with b, creates object with ab, assings object with ab to "a" pointer 
+0

我建议你在依赖这个之前检查字符串类的实现。 至少在Java中,它比现在更聪明。我没有检查.net的实现,但我不明白为什么他们不会进行相同的优化。 – 2008-09-29 16:55:32

Strigbuilder是一个完美的解决由连接字符串引起的内存问题的解决方案。

为了回答您的具体问题,Stringbuilder与常规字符串相比具有恒定的开销,其中字符串的长度等于当前分配的Stringbuilder缓冲区的长度。缓冲区可能是结果字符串大小的两倍,但是在连接到Stringbuilder之前不会再有内存分配,直到缓冲区被填充,所以它确实是一个很好的解决方案。

与字符串相比,这是优秀的。

string output = "Test"; 
output += ", printed on " + datePrinted.ToString(); 
output += ", verified by " + verificationName; 
output += ", number lines: " + numberLines.ToString(); 

此代码具有存储为代码,则在所述的方法创建,一个来自可变2文字四根弦,但它使用六个独立的中间弦,其越来越长。如果这种模式继续下去,它会以指数速率增加内存使用量,直到GC开始清理它。

+0

对于低估这一点的人,请解释。 – torial 2008-09-29 20:58:22

您可能感兴趣的绳索数据结构。本文:Ropes: Theory and practice解释了它们的优点。也许有一个.NET的实现。

[更新,回复评论] 使用较少的内存吗?在文章中搜索内存,你会发现一些提示。
基本上,是的,尽管结构开销,因为它只是在需要时增加内存。当使用旧的缓冲区时,StringBuilder必须分配一个更大的缓冲区(它可能已经浪费了空的内存)并丢弃旧的缓冲区(这将被垃圾收集,但仍然可以使用大量的内存)。

我还没有找到.NET的实现,但至少有一个C++实现(在SGI的STL中:http://www.sgi.com/tech/stl/Rope.html)。也许你可以利用这个实现。请注意我参考的页面有关于内存性能的工作。

请注意,绳索不是解决所有问题的方法:它们的用处很大程度上取决于您如何构建大型字符串以及如何使用它们。文章指出了优点和缺点。

+0

有关它如何执行RAM方式而不是速度方面的任何数据? – torial 2008-09-29 20:59:29