2013-07-09 111 views
7

這在某種程度上是對我的previous question的後續操作。異常緩慢的Javascript循環

我創建a jsPerf其比較多種方式採取RGB像素值

var rgb = [R, G, B, R, G, B...] 

的1維陣列並轉換那些成RGBA值的HTML5畫布(其中所述α信道是總是255,完全不透明)。

var rgba = [R, G, B, 255, R, G, B, 255...] 

在我的測試中,我發現我測試的循環,名爲「For循環」之一,是天文數字比其他循環慢。其他迴路在完成操作每秒數億次時,其重量爲,高達86次/秒。循環可以在上面的jsPerf鏈接中找到,但是這裏有一些代碼用「For循環」和「4 *展開,跳過alpha」,這是測試中更快的循環之一。

//Setup for each test 
function newFilledArray(length, val) { 
    var array = Array(length); 
    for (var i = 0; i < length; i++) { 
     array[i] = val; 
    } 
    return array; 
} 

var w = 160; //width 
var h = 144; //height 

var n = 4 * w * h; //number of length of RGBA arrays 
var s = 0, d = 0; //s is the source array index, d is the destination array index 

var rgba_filled = newFilledArray(w*h*4, 255); //an RGBA array to be written to a canvas, prefilled with 255's (so writing to the alpha channel can be skipped 
var rgb = newFilledArray(w*h*3, 128); //our source RGB array (from an emulator's internal framebuffer) 

//4*unrolled, skip alpha - loop completes (exits) 185,693,068 times per second 
while (d < n) { 
    rgba_filled[d++] = rgb[s++]; 
    rgba_filled[d++] = rgb[s++]; 
    rgba_filled[d++] = rgb[s++]; 
    d++; 
} 

//For Loop - loop completes (exits) 85.87 times per second 
for (var d = 0; d < n; ++d) { 
    rgba_filled[d++] = rgb[s++]; 
    rgba_filled[d++] = rgb[s++]; 
    rgba_filled[d++] = rgb[s++]; 
} 

它怎麼能在語法上如此令人難以置信的相似,但在性能方面卻如此之遠?

+0

您是否嘗試過切換循環的順序 – aaronman

+0

您是否嘗試過使用['dis()'](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Introduction_to_the_JavaScript_shell#dis.28.5Bfunction)。 5D.29)? –

+1

@aaronman你是什麼意思? jsperf在新的JS環境中運行每個測試。 – Barmar

回答

10

只有for循環如此緩慢的原因是因爲它是唯一正確的測試用例;其他所有的測試用例從未復位,除其他外,中d價值,所以在第一次迭代是正常的,其餘的顯然是超級快:)

jsperf給出一個更好的結果,從而使for循環是隻比最快的結果稍慢。

更新

作爲bfavaretto建議,你也應該重新s和你正在爲建設一個更加一致的結果目標陣列。他的結果可以找到here

+2

我認爲他假定在每次迭代測試之前重新運行準備代碼。 – Barmar

+0

@Barmar這將是我的猜測以及:) –

+0

好趕上!令我困惑的是,設置表明它「在每個時鐘測試循環之前,在定時代碼區域之外運行」。這句話仍然表明它聽起來像安裝程序應該運作,因爲我認爲它會! –