lmonninger
lmonninger

Reputation: 961

Are JavaScript Arrays significantly smaller than Objects on the heap?

I'm working with (network) graphs in the browser and was wondering if I can significantly reduce memory usage by changing the way I represent them.

I was thinking of changing the representation of the edges from:

{from : string, to : string, weight : number, bi : boolean}

To:

[string, string, number, boolean]

I recognize that the serialized Object sizes and Array sizes for this particular use case are not that different, particularly if I shorten my keys. But, I'm curious if there is a significant difference between the size of Objects and Arrays on the heap in most browsers. If I'm most concerned about browsers running V8, is there a way to test this in Node?

Note: without the graph portion of my application, my JS heap was already a little large (15 mb for my logic + 50mb for a couple frames). So, there is a bit of justification beyond my curiosity for trying something like this out.

Upvotes: 2

Views: 444

Answers (1)

jmrk
jmrk

Reputation: 40501

(V8 developer here.)

What I'd expect is that the objects are slightly smaller than the arrays in this case. I'd also expect that the difference only matters if you have a lot of objects.

The reason is V8's "hidden classes" system, where the names of the properties are only stored once and shared by all objects with the same "shape", so each object needs 3 pointers (object header) + 4 pointers for the properties, with each pointer being 4 bytes that's a total of 7*4 = 28 bytes. The length of the property names does not affect the per-object memory requirements. Arrays have one more property (.length), and their elements will be stored in a separate backing store, so the total memory consumption for each array should be 3 (object header) + 1 (length) + 2 (backing store header) + 4 (elements) pointers = 10 pointers or 40 bytes.

In a simpler JavaScript engine where all objects are implemented as dictionaries, arrays might indeed save some memory, because each object would store the property names, at least as a pointer to a shared string -- unless, of course, arrays are also implemented as dictionaries in such an engine, in which case they'd again be a bit bigger because they have the additional length property.
Depending on what else you do with your objects, you could make V8 migrate them to dictionary mode (because hidden classes have many benefits and also some disadvantages in some cases), but it's more likely you'll encounter the situation described above.

So, as always for performance and memory questions, the only way to be sure is to implement both approaches in your real app (not in a simplified microbenchmark) and measure the impact. If you can't measure a difference, then there is no difference to worry about.

Upvotes: 4

Related Questions