JS 預分配數組長度,究竟是變慢仍是變快?

在個人上一篇文章 JavaScript 在 V8 中的元素種類及性能優化 中寫道:segmentfault

clipboard.png

V8 的類型轉換隻能經過格子向下過渡。一旦將單精度浮點數添加到 Smi 數組中,即便稍後用 Smi 覆蓋浮點數,它也會被標記爲 DOUBLE。相似地,一旦在數組中建立了一個洞,它將被永久標記爲有洞 HOLEY,即便稍後填充它也是如此。數組

一旦數組被標記爲有洞,它永遠是有洞的 - 即便它被打包了!從那時起,數組上的任何操做均可能變慢。若是您計劃在數組上執行大量操做,而且但願對這些操做進行優化,請避免在數組中建立空洞。V8 能夠更有效地處理密集數組。性能優化

而後有人提出了一個疑問:jsp

爲何先指定長度再初始化測試出來會快一點?函數

其實,二者相比只是「可能」變慢。性能

具體因素有不少,好比預分配一個很大的數組,這時能夠變快,lodash 的 map 函數就是這麼作的。由於初始化的時候分配完空間,就能夠避免在數組空間不夠用的時候反覆的內存申請和 GC 操做。而 FAST_ELEMENTSFAST_HOLEY_ELEMENTS 都不太慢,至少在全部元素中能夠排到前二。測試

https://cs.chromium.org/chrom...優化

數組分配完成後默認是 FAST_HOLEY_SMI_ELEMENTS,當元素中添加了新的非 smi 值時,數據會進行類型轉換。--trace-elements-transitions 的輸出:spa

elements transition [FAST_HOLEY_SMI_ELEMENTS -> FAST_HOLEY_ELEMENTS]

我寫了一個性能測試,對於 HOLEY_ELEMENTS,讀取的時候 HOLEY 慢不少,寫入的時候性能同樣。若是數組很大,預先分配大小後性能反而會提高。code

https://jsperf.com/array-elem...

https://jsperf.com/array-elem...

還有一個重要的性能提示就是:避免讀數超出數組的長度!這樣 V8 會在原型鏈上去找這個屬性。

相關文章
相關標籤/搜索