2

I'm using Chrome Devtools's Heap Snapshot feature, which allows watching the size of objects on my website to measure where/if I need to reduce the size of my objects.

However, I'm looking at the size of an object, which is supposedly 15.5MB, but its parts are only 1.6MB, 1MB, and 0.8MB: enter image description here

Here is the structure of this object for reference (BiMap just being two Records for either direction):

interface Mappings {
    classes: BiMap<string, string>
    noDescriptorToDescriptorMethods: BiMap<string, string>
    descriptorToDescriptorMethods: BiMap<string, string>
}

Unless my math is really rusty and 0.8 + 1 + 1.6 = 15.5, what is going on here?

Hasip Timurtas
  • 983
  • 2
  • 11
  • 20
Fudge Fudge
  • 1,024
  • 1
  • 10
  • 25

1 Answers1

1

This answer on another question answers your question quite well.

Let's first look at the definition of "retained size":

This is the size of memory that is freed once the object itself is deleted along with its dependent objects that were made unreachable from GC roots.

The JS Heap is not a tree but rather a directed graph. In a simple example the retained size of an object will indeed be the sum of the objects referred by it. In the picture below the retained size of Obj1 is the sum of the Obj1 shallow size, and Obj2 and Obj3 retained size:

tree example

However, once this structure is not a tree anymore, this simple addition does not hold anymore. If Obj6 starts referencing Obj5, then Obj5 will not be accessible only from Obj2. So the retained size of Obj2 will now include only Obj4, and will exclude Obj5.

non-tree examle

Now the retained size of Obj1 will stay the same. If garbage collector frees Obj1, it'll free the whole references graph of size 41. However, if garbage collector frees only Obj2, it will not free Obj5, because it would be still referenced by Obj6.

Fabio Bove
  • 11
  • 2