同事報案,用JS Bin跑迴圈計算從1加到n測試效能,發現 for 迴圈次數增加到100萬後加總結果不對,每次執行會得到小於正確值(499999500000)的隨機數字;但若不用for改用lodash _.times(),跑再多次結果也是正確的。

為了調查,先將程式碼簡化到可重現問題的最精簡內容:

    var count = 1000000;
    var sum = 0;
    for (var i=0;i<count;i++)
      sum += i;
    console.log("Inline:"+sum);

發現一個現象,如果用<script>將程式內嵌進HTML,執行結果正確;要移到JavaScript區塊才會出錯,如下例:

Inline測試結果為499999500000,而JavaScript測試結果為每次不同的亂數,然後我還注意到下方有段警告:

Exiting ptoential infinite loop. To disable protection: add "// noprotect" to your code.

JS Bin說它「已跳出潛在無窮迴圈」!

研判這是JS Bin防止程式碼陷入無窮迴圈的機制,當迴圈連續執行超過一定次數就強行中止(聽起來頗神奇,不知是怎麼做到的),但後面的程式碼會繼續執行。中斷時機不一可以解釋為什麼每次跑出的數字不同,而_.times()的演算法不符合潛在無窮迴圈的標準,故未受影響。

要避免保護機制影響執行結果,在程式碼開頭加入// noprotect關掉保護,搞定收工!


Comments

# by TTben

通常工程師都會認為//後面寫註解都一定沒有問題, 但實際上在有些條件下,會造成異常,機率偏低。

Post a comment