日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

索引超出数组界限是什么意思_从V8源码分析一个JS 数组的内存占用问题

發(fā)布時間:2023/12/10 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 索引超出数组界限是什么意思_从V8源码分析一个JS 数组的内存占用问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前段時間,在排查一個問題的時候,遇到了一個有點令人困惑的情況,有下面這兩段代碼:

const a = new Array(99999); a[99998] = undefined;const b = new Array(99999); b[99999] = undefined;

我們通過 node --inspect-brk 來分別運行這兩段代碼,在代碼運行的最開始和結(jié)束的時候分別task heap snapshot,分析對應的內(nèi)存占用信息如下:

可以發(fā)現(xiàn)第二段代碼的內(nèi)存占用明顯要小于第一段,那么問題就出現(xiàn)在這個 99999 的越界賦值上面。

在V8代碼(v8/src/objects/js-array.h#L19)中有很明確的標注,數(shù)組有兩種模式,快數(shù)組和慢數(shù)組,在數(shù)組初始化時,默認的存儲方式為快數(shù)組(v8/src/objects/js-objects.h#L317),其內(nèi)存占用是連續(xù)的,而慢數(shù)組會使用HashTable來進行數(shù)據(jù)存儲。 另外數(shù)組會分為壓緊(Packed)的和有洞的(Holey)兩種,例如 ['a', 'b', 'c'] 這樣的數(shù)組長度為3,數(shù)組索引0、1、2均有值,那么就認為是Packed;而對于 ['a',,,'d'] 這樣的數(shù)組,長度為4,但是索引1、2位置并沒有進行初始化賦值,那么就認為是Holey。當數(shù)組出現(xiàn)了較大空洞的時候,內(nèi)存明顯是被浪費了。

V8中對于大型空洞數(shù)組進行了優(yōu)化,在V8博客(https://v8.dev/blog/fast-properties)中進行說明了這一點,對于非常大的Holey數(shù)組來說,FixedArray會造成內(nèi)存浪費,所以會使用字典來節(jié)約內(nèi)存,也就是會使用慢數(shù)組模式。

使用v8-debug分別對最開始的兩段代碼進行調(diào)試:

可以很明顯的看到,第一個數(shù)組為FixedArray,而第二個數(shù)組為Dictionary,那么為什么只有第二個數(shù)組轉(zhuǎn)換為了字典模式呢?

在V8中JSArray是繼承于JSObject的,所以當設置屬性的時候,會依次執(zhí)行 Object::SetProperty 、 Object::AddDataProperty 、 JSObject::AddDataElement 、 ShouldConvertToSlowElements ,回到V8代碼中,ShouldConvertToSlowElements這個方法,它是用來判斷是否將一個數(shù)組轉(zhuǎn)換為慢模式(Dictionary)(v8/src/objects/js-objects-inl.h#L794):

從上面的代碼可以看到,當設置 99998 的時候,索引小于當前容量的時候,返回值為false,也就是不進行轉(zhuǎn)換。 而當設置 99999 這個索引的值的時候,因為超出了原來的FixedArray容量,那么就會進行擴容,擴容的算法(v8/src/objects/js-objects.h#L540)為容量 + 容量 /2 + 16,那么原來 99999 的容量就會擴容放大到 15萬。

然后會執(zhí)行 GetFastElementsUsage 來獲取原來的數(shù)組中非空洞(v8/src/objects/js-objects.cc#L4725)的元素數(shù)量,乘以 kPreferFastElementsSizeFactor(值為3) 與 kEntrySize (值為2) ,與新的容量長度進行對比,如果小于新的容量長度,那么就轉(zhuǎn)換為慢數(shù)組。

最開始的第二段代碼中,非空洞元素數(shù)量為0,計算后的乘積也為0,因此小于15萬的新數(shù)組長度,于是數(shù)組轉(zhuǎn)換為了慢數(shù)組,使用了Dictionary進行數(shù)據(jù)的存儲,從而節(jié)省了大量的內(nèi)存。

總結(jié)

以上是生活随笔為你收集整理的索引超出数组界限是什么意思_从V8源码分析一个JS 数组的内存占用问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。