【问题标题】:Javascript - Fastest way of copying an array portion into anotherJavascript - 将数组部分复制到另一个的最快方法
【发布时间】:2009-09-19 16:55:27
【问题描述】:

我需要将一个数组的一部分FAST复制到另一个数组中,替换它的旧值。

  • 无需范围检查。
  • 要复制的项目数:16384
  • 数组只包含整数

基准代码: http://codebase.es/test/copytest.htm

这是我的方法:

  var i = 0x4000>>5; // loops count
  var j = 0x4000;    // write start index
  var k = 0x8000;    // read start index
  while (i--) {      // loop unrolling
    dst[j++]=src[k++]; dst[j++]=src[k++];
    dst[j++]=src[k++]; dst[j++]=src[k++];    
    dst[j++]=src[k++]; dst[j++]=src[k++];
    dst[j++]=src[k++]; dst[j++]=src[k++];
    //8
    dst[j++]=src[k++]; dst[j++]=src[k++];
    dst[j++]=src[k++]; dst[j++]=src[k++];    
    dst[j++]=src[k++]; dst[j++]=src[k++];
    dst[j++]=src[k++]; dst[j++]=src[k++];
    //16
    dst[j++]=src[k++]; dst[j++]=src[k++];
    dst[j++]=src[k++]; dst[j++]=src[k++];    
    dst[j++]=src[k++]; dst[j++]=src[k++];
    dst[j++]=src[k++]; dst[j++]=src[k++];
    //24
    dst[j++]=src[k++]; dst[j++]=src[k++];
    dst[j++]=src[k++]; dst[j++]=src[k++];    
    dst[j++]=src[k++]; dst[j++]=src[k++];
    dst[j++]=src[k++]; dst[j++]=src[k++];
    //32
  }    

这可以更快地完成吗?

【问题讨论】:

  • 使用 pre-decremet/pre-increment 而不是 post-decrement/post-increment 可能会带来轻微的性能提升。
  • 秋葵,你是对的。它有点快。如果您将评论写为答案并且没有最佳解决方案,我会给您
  • 我知道这已经很晚了,但很好奇。为什么不只是 var dst = src.concat() ?我认为这可能是克隆数组的最快方法。不过,这不是深拷贝。对于深拷贝循环是唯一的方法。

标签: javascript arrays copy performance


【解决方案1】:

我不确定你的方法是否比这更快:

var i = 0x4000;     // loops count
var j = 0x4000;    // write start index
var k = 0x8000;    // read start index
while (i--) {      // loop unrolling
  dst[j++]=src[k++];
}

【讨论】:

【解决方案2】:

您可以继续展开循环以稍微提高性能,但看起来这与您将获得的速度一样快。正如 Gumbo 在评论中所说,尝试使用前增量而不是后增量:

var i = 0x4000>>5 + 1; // loops count
var j = 0x4000 - 1;    // write start index
var k = 0x8000 - 1;    // read start index
while (--i) {      // loop unrolling
    dst[++j]=src[++k]; dst[++j]=src[++k];
    dst[++j]=src[++k]; dst[++j]=src[++k];    
    dst[++j]=src[++k]; dst[++j]=src[++k];
    dst[++j]=src[++k]; dst[++j]=src[++k];
    //8
    ...

【讨论】:

    【解决方案3】:

    我会考虑切片方法:

    var dst = src.slice(start,end)
    

    性能取决于javascript引擎的实现,但想必所有浏览器都在其平台上尽可能高效地实现了。

    查看更多here

    【讨论】:

    • 他要求替换另一个数组的内容,而不是形成一个新的。
    • @cemkalyoncu:然后做slicesplice
    • “Slice and splice”听起来像是电视直接响应产品。 “厌倦了编写笨拙的 for 循环?试试新的 Slice 和 Splice!它会切片,它会拼接,它消除了数组处理的痛苦。现在订购只需 19.95 美元!”
    • slice + splice 要慢得多。看副本3:codebase.es/test/copytest.htm
    【解决方案4】:

    抱歉,一年后,但是..这是 FF 中最快的:

    function copy4() {
      var i = 0x4000; // loops count
      var j = 0x4000; // write start index
      var k = 0x8000; // read start index
    
      var args = src.slice(k, k+i);
      args.unshift(i);
      args.unshift(j);
      Array.prototype.splice.apply(dst,args);
    }
    

    【讨论】:

      【解决方案5】:

      另一种值得进行基准测试的方法可能是构建一个全新的 dst 数组,只使用一些强大的原语而不是执行循环,即:

      dst = dst.slice(0, writestart).concat(
          src.slice(readstart, readstart+count),
          dst.slice(writestart+count));
      

      与循环相比,这种方法的性能无疑会随着所涉及的数组长度和计数以及底层 Javascript 引擎的不同而有所不同——猜测不会很有成效,这就是我建议进行基准测试的原因;- )。

      【讨论】:

      • 这大约慢了 10 倍
      • 一些很可能用 C++ 编写的内部函数比解释一堆行的速度慢,奇怪。顺便说一句,我在 C 中测试了相同的代码,结果复制时间为 6-14 毫秒(1000 x 0x4000 元素)
      • 现代浏览器将 javascript 编译成机器码。例如 Chrome 的 V8 和 FF 的 TraceMonkey。
      【解决方案6】:

      尝试结合内置方法slicesplice

      Array.prototype.splice.apply(dst, [j, i].concat(src.slice(k, k+i)));
      

      【讨论】:

      • 对不起。您的解决方案大约慢了 50 倍。
      • 如果你想让它表现良好,就不要。
      【解决方案7】:

      您可以创建一个完全展开的版本,例如通过

      function compileCopy(count, di, si) {
          var sb = new Array(count);
          di += count, si += count;
          while(count--) sb[count] = --di + ']=src[' + --si;
          return new Function('dst[' + sb.join('];dst[') + '];');
      }
      
      var copy = compileCopy(0x4000, 0x4000, 0x8000);
      

      在 Opera 中,它会比循环版本稍快。在 FF 中......不是(甚至可能在某处存在一些错误)。

      【讨论】:

      • 但是起始索引被硬编码到“编译”函数中。对于每个复制调用,您都需要再次“编译”它。
      • 但它们可以是函数参数而不会造成性能损失。
      猜你喜欢
      • 2012-11-01
      • 2017-04-03
      • 1970-01-01
      • 2015-06-17
      • 1970-01-01
      • 2014-06-18
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多