代码之家  ›  专栏  ›  技术社区  ›  torial

StringBuilder的RAM消耗情况如何?

  •  6
  • torial  · 技术社区  · 16 年前

    我们有一些操作正在进行大量的大字符串连接,最近遇到了内存不足异常。不幸的是,调试代码不是一个选项,因为这是在客户站点上发生的。

    因此,在对代码进行全面检查之前,我想问:StringBuilder对于大字符串的RAM消耗特性是什么?

    尤其是与标准字符串类型相比。字符串的大小远远超过10MB,我们似乎遇到了20MB左右的问题。

    笔记

    5 回复  |  直到 15 年前
        1
  •  10
  •   Bob King    16 年前

    每次StringBuilder耗尽空间时,它都会重新分配一个新缓冲区,大小为原始缓冲区的两倍,复制旧字符,并让旧缓冲区获得GC'd。您可能只是使用了足够的内存(称为x),因此2x比允许分配的内存大。您可能需要确定字符串的最大长度,并将其传递给StringBuilder的构造函数,以便进行预分配,而不受加倍重新分配的影响。

        2
  •  6
  •   Pascal Paradis    16 年前

    String Concatenation vs Memory Allocation .

    如果你不这么做的话,这是一个不需要动脑筋的问题 必须连接,但希望 源代码看起来不错,使用 第一种方法。它将根据需要进行优化

    永远不要使用+=连接。 正在发生太多的变化 从我的代码开始。我 显式地使用任何重载(2 这将清楚地显示您的代码是什么 没有任何意外,而 效率。

    尝试估计StringBuilder的目标大小。

    你可以更准确地估计 创建以增加其内部 缓冲器

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

    您所使用的是{x}替换。 Format()有利于可读性,但 挤出所有可能的性能 你的申请。

        3
  •  3
  •   PhiLho    16 年前

    Ropes: Theory and practice 解释了它们的优势。也许有一个.NET的实现。

    它使用更少的内存吗?搜索 在本文中,您将发现一些提示。
    基本上,是的,尽管结构开销很大,因为它只是在需要时添加内存。StringBuilder在耗尽旧缓冲区时,必须分配一个大得多的缓冲区(这可能会浪费空内存)并丢弃旧缓冲区(这将被垃圾收集,但同时仍会占用大量内存)。

    http://www.sgi.com/tech/stl/Rope.html )。也许您可以利用此实现。注意,我引用的页面有一个关于内存性能的工作。

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

        4
  •  1
  •   Jeffrey L Whitledge    16 年前

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

    为了回答您的特定问题,Stringbuilder的开销是恒定的,而普通字符串的长度等于当前分配的Stringbuilder缓冲区的长度。缓冲区的大小可能是结果字符串的两倍,但在缓冲区填满之前,连接到Stringbuilder时不会再进行内存分配,因此这确实是一个很好的解决方案。

    与string相比,这是非常出色的。

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

    这段代码中有四个字符串作为文本存储在代码中,两个是在方法中创建的,一个是从变量中创建的,但是它使用了六个独立的中间字符串,它们越来越长。如果这种模式继续下去,它将以指数级的速度增加内存使用,直到GC开始清理它。

        5
  •  -2
  •   albertein    16 年前

    我不知道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