在JS中超过700毫秒的800万次迭代是可以的吗?怎么加快?

时间:2012-12-04 12:09:05

标签: javascript performance

我有一个游戏并初始化地图2000 x 4000块。 它只在onLoad上运行一次,需要大约700ms。我怎样才能加快速度?其他逻辑取决于此映射。 这是代码:

var start = new Date();
var g = {};
g.world = { h:2000, w:4000, cellInfo: [] };
var i, j,
    world = g.world,
    hlim = world.h,
    wlim = world.w,
    cellInfo = world.cellInfo;
for ( i = hlim; i; i--) {
    cellInfo[i] = [];
    for (j = wlim; j; j--) {
        cellInfo[i][j] = 1;
    }
}
g.world.cellInfo = cellInfo;
alert(new Date() - start);​

这是小提琴:http://jsfiddle.net/NSX9z/

1 个答案:

答案 0 :(得分:6)

为您提供几种选择:

Lazy init

加速它的最佳选择是使用延迟初始化。例如,不是初始化所有800万个插槽,而是依赖于它们的代码,如果它们不存在则处理它。例如,获得一个单元格

function getCell(x, y) {
    var row, cell;

    row = cellInfo[x];
    if (!row) {
        row = cellInfo[x] = [];
    }

    cell = row[y];
    if (typeof cell === "undefined") {
        cell = row[y] = 1; // 1 appears to be the default value
    }

    return cell;
}

...和setCell类似。这扩展了init。当然,这意味着事情稍微慢一些,尽管它不太可能是明显不同的。

阵列克隆

如果你不这样做,另一个选择是创建一次4,000个插槽的数组,然后克隆它而不是手工创建它,希望在JavaScript引擎中完成工作比实际循环更快自己:

// ...
var the4k = [];
// ...build it...
// Now use it for one row and clone it for the others
cellInfo[hlim] = the4k;
for ( i = hlim - 1; i; i--) {
    cellInfo[i] = the4k.slice(0);
}

对我来说阵列克隆speeds things up dramatically,Chrome从~780ms到~130ms,IE9从~530ms到~50ms。

要考虑的另一个问题是,在IE8及更早版本中,“慢速脚本警告”不是基于时间,而是基于操作次数。你的小提琴给了我IE8上的慢脚本警告。我没有。

IE8争论lazy-init,因为它甚至需要 9秒来运行我的小提琴版本。