Javascript - 将阵列部分复制到另一个阵列部分的最快方法

时间:2009-09-19 16:55:27

标签: javascript arrays copy performance

我需要将 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
  }    

可以更快地完成吗?

7 个答案:

答案 0 :(得分:3)

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

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++];
}

答案 1 :(得分: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
    ...

答案 2 :(得分:1)

我会考虑切片方法:

var dst = src.slice(start,end)

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

查看更多here

答案 3 :(得分:1)

抱歉,一年后,但是......这是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);
}

答案 4 :(得分:0)

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

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

这种方法与循环相比的性能无疑会随着所涉及的数组长度和数量以及底层的Javascript引擎而变化 - 猜测效率不高,这就是为什么我建议使用基准测试; - )。

答案 5 :(得分:0)

尝试使用内置方法slicesplice组合:

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

答案 6 :(得分:0)

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

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 ...没有(某处甚至可能存在某些错误)。