Chrome 内存快照中的保留大小 - 到底保留了什么?

问题描述 投票:0回答:1

浏览器文档保留尺寸 是 "一旦对象本身连同其从GC根部变得不可及的依赖对象被删除后,被释放的内存大小",这很公平。但是,即使是简单的对象,保留的大小往往是浅层大小的3倍。我理解V8需要存储对隐藏形状的引用,可能是GC的一些数据等等,但有时对象有几百个额外的 "保留 "字节,当你需要有几百万个这样的对象时,这似乎是一个问题。我们来看看一个简单的例子。

class TestObject {
    constructor( x, y, z ) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

window.arr = [];
for ( let i = 0; i < 100000; i++ ) {
    window.arr.push( new TestObject( Math.random(), Math.random(), Math.random() ) );
}

这是内存快照

Memory snapshot, shallow size is 24 bytes and retained size is 60 bytes

Shallow size is 24 bytes, which is perfectly matches with the fact that we're storing 3 x 8 -byte doubleles. "Extra" size is 36 bytes. "Extra "大小是36字节,允许存储9 x 4字节的指针(假设指针压缩开启)。如果我们添加三个额外的属性,额外的大小将是72(!)字节,所以这取决于属性的数量。那里存储的是什么?有没有可能避免如此巨大的内存开销?

javascript google-chrome memory google-chrome-devtools v8
1个回答
2
投票

我是V8开发者。

浅显的大小是对象本身,由标准对象头(3个指针)和3个对象内属性组成,这些属性又是指针。也就是6个(压缩的)指针,每个4字节=24字节。

额外保留的大小是三个属性的存储。每一个属性都是一个 "HeapNumber",由一个4字节的映射指针加上一个8字节的有效载荷组成。所以就是3个属性乘以12字节=36字节。(有了这些知识,如果再加上另外三个属性(大概也是数字),这个数字翻倍为 72,也就不足为奇了。)

加起来,每个对象总共占用24+36=60个字节。

Map和prototype不计入每个对象的保留大小,因为它们是所有对象共享的,所以释放一个对象不会让它们也被释放。

一个节省内存的想法(如果你觉得很重要的话)是 "换位 "你的数据组织:你可以有1个对象,包含3个数组,每个数组包含10万个对象,而不是1个数组,每个数组包含10万个数字。根据你的用例,这可能是一个可行的方法,也可能不是:如果三组数字来来往往,那么将它们存储在一个巨大的数组中会让人不愉快;而如果是静态数据集,那么这两种模式在可用性上可能相当相当。如果你这样做,就可以避免每个对象的重复开销;另外数组可以内联存储双数(只要整个数组包含 只是 数字),所以你将能够存储同样的300K数字,而总内存消耗只有2.4MB。

如果你试着用许多小的TypedArrays来代替3个属性的对象,你会发现内存使用量会显著增加,因为TypedArrays的每个对象开销比简单对象大得多。它们面向的是有几个大的数组,而不是很多小的数组。

© www.soinside.com 2019 - 2024. All rights reserved.