【问题标题】:String concatenation is extremly slow when input is large当输入很大时,字符串连接非常慢
【发布时间】:2009-10-08 07:53:52
【问题描述】:

像下面的代码这样的东西超级慢:

var str:String = ""
for (var i:Number = 0 ; i<1000000000000000000 ; ++i) {
    str += "someLongLongLongLongLongLongLongLongLongString";
}

Java 中有StringBuilder,但似乎没有与 AS 对应的。 那么,你们如何处理大字符串连接?


更新:

谢谢大家的回答!

我刚刚编写了自己的testing program。使用+= 已经是最快的了……慢的是把它放在TextArea 上……

我投票支持你们中的大多数人,因为这些建议是有道理的 :) 虽然我的测试结果表明我的问题似乎有些问题,因为我要求的东西比已经最好的东西更好:P

【问题讨论】:

    标签: flash actionscript-3 string concatenation


    【解决方案1】:
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
    performancetests.Strings (1 iterations)                                 
    Player version: MAC 10,0,32,18 (debug)
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
    method...................................................ttl ms...avg ms
    stringsWithConcatMethod                                   17555 17555.00
    stringsWithPlusConcat                                      4972  4972.00
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
    

    我不是受虐狂,所以我只使用了 10000000 次迭代循环:

    var str:String = ""
    for (var i:Number = 0 ; i<10000000 ; ++i) {
        str += "someLongLongLongLongLongLongLongLongLongString";
    }
    

    对比:

    var str:String = ""
    for (var i:Number = 0 ; i<10000000 ; ++i) {
        str = str.concat("someLongLongLongLongLongLongLongLongLongString");
    }
    

    使用Grant Skinner's AS3 Performance Test Harness。 String::concat 方法甚至更慢,尽管考虑到您的条件 as3 可能只是 sloooow。 (结果中的 1 次迭代是 1 次经过 10000000 次迭代循环)。我对结果相当惊讶。我认为 concat 会更快。

    【讨论】:

    • 感谢您的测试(+1 :))!你也让我编写自己的测试程序!查看我的问题更新:)
    • -1,在每次迭代时扩展字符串 - 无论方法如何 - 都是 O(n^2) 并且是错误的方法。
    【解决方案2】:

    是的,即使使用StringBuilder很慢。我的问题是:你为什么要创建一个大小为 46 EB 的字符串?

    在某些时候,更传统的外部存储(即磁盘上)方法会成为一个好主意,但您似乎甚至已经通过了这一点(基于当今常用的磁盘阵列)。

    我一般不会遇到这个问题,因为我倾向于不使用字符串来存储这么大的东西。字符串通常用于较小的对象。您所拥有的是一个相当大的数据仓库,而不是名称或地址字段:-)

    【讨论】:

    • 我知道你的意思。但有时我们别无选择,因为 UI 组件使用 String...
    【解决方案3】:

    我不能说我对 ActionScript 很有经验,但对于一般的 ECMAScript,我发现数组可以帮助加快字符串连接(JavaScript 示例如下):

    var sb = [];
    for (var i = 0; i < 10000000000; i++) {
        sb.push('longlonglong');
        // In this particular case you can avoid a method call by doing:
        //sb[i] = 'longlonglong';
    }
    var str = sb.join('');
    

    【讨论】:

    • +1,因为这对于大多数 JS 解释器都是正确的(尽管sb[i] = 'longlonglong' 似乎更快......对于 AVM2,这个技巧不管用 push 还是用数组访问...
    • 哎呀,抱歉冗余,没有完全阅读评论行... :)
    • 我刚刚发现即使是JS,+=也是最快的!查看我的问题更新!
    【解决方案4】:

    有两件事通常会使此类操作变慢:

    • 字符串超出为其分配的内存,因此必须重新分配。这涉及堆内存管理器和复制内容。随着内容的增长,这意味着它会被大量复制,并且内存系统必须非常努力地工作。
    • 如果字符串的存储方式不意味着其长度可用作 O(1) 操作,则连接首先必须遍历整个字符串以找到长度,即从哪里开始连接。这意味着每个连接所花费的时间与目标字符串的长度成正比。

    我确信其中至少有一个对您有影响(后者可能不会,不确定字符串在 ActionScript 内部是如何表示的)。

    【讨论】:

      【解决方案5】:

      你在这里进行类型滥用......:D......在AVM2上,字符串用于文本表示......它们始终是unicode,这就是为什么它们每个字符需要超过2个字节......所以它们不适合存储 i-will-make-your-heap-explode 大小的 ascii 序列...如果您真的想处理大量数据,请选择flash.utils::ByteArray ...并不是特别更快,但它在语义上更正确并且内存占用更少......加上它具有本机压缩方法,这是我强烈推荐的情况......:P

      【讨论】:

      • 感谢您的建议!这就是我最初的想法。但是我发现String的+=是最快的:P 因为我要显示文本,所以无论如何都需要创建一个String...
      猜你喜欢
      • 2010-11-10
      • 2011-12-23
      • 2015-12-02
      • 2018-03-09
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-05
      相关资源
      最近更新 更多