因此,在着手改进我们的代码之前,我想问一下:当处理大字符串时,StringBuilder 的内存消耗特性如何?特别是与标准的 string 类型相比较而言。这些字符串的大小远超过10 MB,并且似乎在20 MB左右就会出现问题。
请注意:此问题与速度无关,而是与内存有关。
这里有一份关于字符串拼接与内存分配的研究报告。
如果可以避免拼接字符串,就尽量避免!
这是显而易见的,如果你不必拼接字符串但仍想保持代码美观,那么使用第一种方法。它将被优化为一个单独的字符串。
永远不要使用 += 拼接字符串。太多的变化正在后台发生,这些变化并不明显。我建议明确地使用 String.Concat(),使用任何重载(2个字符串、3个字符串、字符串数组)。这将清楚地显示你的代码在做什么,没有任何意外,并允许你保持效率。
尝试估算 StringBuilder 的目标大小。
你越能够准确地估算所需的大小,StringBuilder 就需要创建的临时字符串越少,以增加其内部缓冲区。
当性能成为问题时,请不要使用任何 Format() 方法。
过多的开销涉及到解析格式,而当你只使用 {x} 替换时,你可以将数组构造出来。Format() 对可读性有好处,但当你将所有可能的性能挤出你的应用程序时,它是要被放弃的事情之一。
Strigbuilder是解决由于字符串拼接导致的内存问题的完美解决方案。
回答你具体的问题,与普通字符串相比,Stringbuilder有一个固定大小的开销,其中字符串的长度等于当前分配的Stringbuilder缓冲区的长度。缓冲区可能最多是结果字符串的两倍大小,但在将字符串连接到Stringbuilder时,不会进行更多的内存分配,直到填满缓冲区,所以这确实是一个出色的解决方案。
与字符串相比,这是杰出的。
string output = "Test";
output += ", printed on " + datePrinted.ToString();
output += ", verified by " + verificationName;
output += ", number lines: " + numberLines.ToString();
这段代码有四个字符串,它们作为字面量存储在代码中,另外两个字符串是在方法中创建的,还有一个来自变量。但是它使用了六个单独的中间字符串,这些字符串会越来越长。如果这种模式继续下去,它将以指数级别增加内存使用率,直到GC启动清理它。
我不确定字符串构建器的内存模式,但普通字符串不是一个好选择。
当你使用普通字符串时,每次连接都会创建另外一对字符串对象,内存消耗急剧增加,导致垃圾回收器被频繁调用。
string a = "a";
//creates object with a
a += "b"
/creates object with b, creates object with ab, assings object with ab to "a" pointer