My code was using too much memory, so I had a look at how much memory a bunch of strings, objects, numbers and arrays take up.
Here are the results:
I think my main takeaway from this data is that even empty arrays and lists are relatively chunky.
The particular problem I was running into was that I created lots of empty lists, rather than re-using the same empty list every time.
Total MB | Bytes Each | |
---|---|---|
Empty Fields | 7.63 | 8.00 |
Booleans | 9.27 | 9.72 |
Numbers | 9.27 | 9.72 |
Identical Strings | 9.27 | 9.72 |
Arrays | 39.79 | 41.72 |
Empty Objects | 62.68 | 65.72 |
I don’t fully understand these results. They depend on the internals of the JavaScript engine.
The size for empty fields makes sense. Each item takes up exactly 8 bytes. (The whole array actually takes up 8,000,048 bytes, so we’ve got 48 bytes of overhead for the array itself.)
However, my expectations don’t match up for the numbers array. JavaScript uses double-precision (64-bit) floating point numbers. 64 bits are 8 bytes, but each number actually takes up an average of 9.7 bytes.
Likewise, Chrome shows the size of each individual empty array as 32 bytes and the size of each empty object as 56 bytes. The whole array however gives an average size of 39.8 and 62.7 respectively.
My guess is that part of this discrepancy comes from V8 storing metadata (e.g. type) for the array items, and from Chrome making more space for the array than the minimum it requires. Also, not all arrays are the same internally in V8. I tried to get a better understanding, but didn’t manage to make much sense of the code. This blog post from 2011 could also be interesting.
If you want to play with the memory profiler in Chrome you can use this CodePen or get the code from Github.
It’s also interesting to see what the table looks like with only item in each array:
Total Array Size | |
---|---|
Empty Field | 56 |
Boolean | 184 |
Number | 184 |
String | 216 |
Array | 216 |
Empty Object | 240 |