8

我正在编写一个函数,将图像逐个像素地绘制到画布元素上。我注意到有一点,该函数的处理时间突然比以前更长 - 特别是从 338x338 像素画布到 339x339 像素画布。

将类似的外观功能放入 jsfiddle,我得到相同的结果。处理 338x338 数组的 while 循环大约需要。6-7 秒,而 339x339 的数组大约需要。24-25 秒。

这发生在 Chrome 上。在 Firefox 中,两者都需要大约。16 秒。

这是小提琴:http: //jsfiddle.net/8pb89/5/

代码如下所示:

var ary1 = [];
var ary2 = [];
var mapData = {};
var colorMatrix = {};

for (var i = 0; i < (338 * 338); i++) {
    ary1.push([i, i + 2]);
}

for (var i = 0; i < (339 * 339); i++) {
    ary2.push([i, i + 2]);
}

//Light operation
function test(i, j) {
    return Math.floor((i * j + i + j) / j);
}

//Heavy operation on objects
function calcTest(ary){
    var point = ary.splice(0, 1);
    var i = point[0];
    var j = point[1];

    if (!mapData[i]) {
        mapData[i] = [];
    }
    if (!mapData[i][j]) {
        mapData[i][j] = [];
    }

    mapData[i][j]["one"] = test(i, j);
    mapData[i][j]["two"] = test(i, j);

    colorMatrix[mapData[i][j]["two"]] = mapData[i][j]["one"];

}

var len = ary1.length;
var start = new Date().getTime();

while (len--) {
    calcTest(ary1);
}

var end = new Date().getTime();
var time = end - start;
alert('Execution for 338x338: ' + time);

var len2 = ary2.length;
obj = {};
obj2 = {};

start = new Date().getTime();
while (len2--) {
    calcTest(ary2);
}
end = new Date().getTime();
time = end - start;
alert('Execution for 339x339: ' + time);

这是 Chrome 上的 javascript 的内存问题,还是我对对象做错了什么?有没有办法避免这种更高的处理时间?

4

2 回答 2

1

我猜它是以下一种或两种。

  • Chrome 正在调整底层哈希表的大小,介于338 * 338和之间339 * 339
  • 垃圾收集发生在同一时间范围内。

我怀疑这是内存问题。

于 2013-07-17T20:05:46.317 回答
1

考虑一下您的 SPLICE 操作实际上在做什么。让我们通过拼接这个数组:

[0,1,2,3,4,5]

我必须:

STORE the 0
READ the 1, WRITE to where the 0 was
READ the 2, WRITE to where the 1 was
READ the 3, WRITE to where the 2 was
READ the 4, WRITE to where the 3 was
READ the 5, WRITE to where the 4 was
DELETE the 5

那是 12 次操作(在一个有 6 个项目大的数组上)......你的数组要大得多(超过 100k 个项目)......你正在迭​​代它们,在你去的时候减少它们。我在你的代码中做了大约 260 亿次计算!!!

我已经重构了您的代码以将 while 循环放入测试中并且不使用 SPLICE 函数 - 我现在在我的机器上将测试降低到 23 毫秒和 25 毫秒(实现与您的测试相同的结果)......您的示例采用3599 毫秒和 19464 毫秒 - 效率提高了近 500 倍 :)

这段代码还有很多其他问题,但这就是你最大问题的核心!

var ary1 = [];
var ary2 = [];
var mapData = {};
var colorMatrix = {};

for (var i = 0; i < (338 * 338); i++) {
    ary1.push([i, i + 2]);
}

for (var i = 0; i < (339 * 339); i++) {
    ary2.push([i, i + 2]);
}

//Light operation
function test(i, j) {
    return Math.floor((i * j + i + j) / j);
}

//Heavy operation on objects
function calcTest(ary){
    for (index=ary.length-1;index>=0;index--){
        var point=ary[index];

        var i = point[0];
        var j = point[1];

        if (!mapData[i]) {
            mapData[i] = [];
        }
        if (!mapData[i][j]) {
            mapData[i][j] = [];
        }

        mapData[i][j]["one"] = test(i, j);
        mapData[i][j]["two"] = test(i, j);

        colorMatrix[mapData[i][j]["two"]] = mapData[i][j]["one"];
    }
}

//I'm only putting the following lines in first to show that the first
//Operation takes longer by populating the mapData and colorMatrix arrays
//If you delete the next two lines you'll find that the 339 option takes
//less time than the 338 (because it's going second!)
calcTest(ary1);
calcTest(ary2);

var start = new Date().getTime();
calcTest(ary1);
var end = new Date().getTime();
var time = end - start;
alert('Execution for 338x338: ' + time);

start = new Date().getTime();
calcTest(ary2);
end = new Date().getTime();
time = end - start;
alert('Execution for 339x339: ' + time);
于 2013-07-19T10:33:59.163 回答