2013-07-17 49 views
8

我正在寫一個函數,它會逐個像素地將圖像繪製到畫布元素。我注意到有一點,函數突然花了比以前更長的時間 - 特別是從338x338像素畫布到339x339像素畫布。兩個幾乎相似的循環之間的非常高的處理差異

把一個類似的功能放到jsfiddle中,我得到了同樣的結果。 while循環處理一個338x338的數組需要約。 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,還是我做一些錯誤的對象呢?有沒有辦法避免這個更高的處理時間?

+2

有趣。 http://jsperf.com/chrome-loops-test – climbage

+0

我不知道這是應該做什麼,但在'calcTest'函數中有很多錯誤。你想介紹一下嗎? – Bergi

+0

小提琴只是我的功能的簡化版本,所以我可以測試338x338和339x339陣列之間的區別。在最終的程序中,數組(ary1/ary2)包含尚未處理的座標。 calcTest函數計算座標的像素顏色,並將數據存儲在mapData對象和colorMatrix對象中(在上例中重命名) – LongInt

回答

1

我猜測它是下面的一個或兩個。

  • 鉻某處調整338 * 338339 * 339之間的基本哈希表。
  • 垃圾收集發生在同一時間範圍內。

我懷疑這是一個記憶問題。

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物品很大)......你的陣列很多,大得多(超過10萬個物品)......並且你在迭代它們,在你走的時候削減它們。我在你的代碼中做了大約260億次的計算!

我已經重新分解代碼把while循環測試中,並且不使用拼接功能 - 我現在得到的測試到我的機器上23MS和25ms的(達到相同的結果你的測試)..你的例子花費了3599ms和19464ms - 這是效率的近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); 
+0

感謝您的優化,我將這作爲一個業餘愛好項目來完成,所以對javascript沒有多少經驗。如果你想提及你看到的其他問題,我也會非常歡迎,因爲它會幫助我學習。 – LongInt

相關問題