1
var Arr1;
var Arr2 = [];

(Assume Arr1 starts as an undefined var and it becomes an array later as needed.)

Would a billion of Arr1 have the same memory footprint as a billion of Arr2? They are both technically empty, but Arr2 is an object which means there must be some overhead in the definition of the object itself, right?

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
Thomas An
  • 503
  • 2
  • 7
  • 17
  • Not the same language, but the same procedure: https://stackoverflow.com/a/2430672/6634591 – Luca Kiebel May 27 '17 at 22:08
  • The real question should be what application design requires you to have thousands of unused arrays in memory? – ste2425 May 27 '17 at 22:45
  • 1
    @ste2425: Doesn't matter. While designing with efficiency in mind we always go to the boundary conditions and see what happens at the extreme. However, I can give you an example too: Suppose we have a WebGL game where each screen object could be a collection of lines, polylines, curves, and surfaces, but suppose today all screen objects happen to be 1 million surfaces so we don't want the unused line/polylines/curves, object properties to add too much to the memory footprint. – Thomas An May 27 '17 at 22:53

2 Answers2

3

TL;DR: about 90 bytes.


I took some measurements in Firefox and Chrome (both on Windows, 64-bit). Firefox’s are much more precise thanks to about:memory, but the impression you get in Chrome is also clear. (I took several measurements after loading the page and waiting for it to settle, then took the best of them.)

My test document contained a doctype and one script block only.

  • Baseline (no arrays):

    var x = [];
    for (var i = 0; i < 0; i++) {
        x.push([]);
    }
    

    Firefox: js-realm memory usage is 0.60 MB.

    Chrome: memory footprint for the tab is 20,880K.

  • A million undefineds or nulls: (memory footprints were the same)

    var x = [];
    for (var i = 0; i < 1000000; i++) {
        x.push(undefined);  // or x.push(null)
    }
    

    Firefox: js-realm memory usage is 8.1 MB, of which class(Array)/objects is 8.00MB, all malloc-heap. (That suggests that it allocated one word for each of the million indexes in the containing array.)

    Chrome: memory footprint for the tab is 31,020K. (Sounds like about 10 bytes per undefined.)

  • A million arrays:

    var x = [];
    for (var i = 0; i < 1000000; i++) {
        x.push([]);
    }
    

    Firefox: js-realm memory usage is 99.65 MB, of which class(Array)/objects is 99.55 MB, of which 91.55 MB is gc-heap and 8.00 MB is malloc-heap. Sounds like about 96 bytes (12 words) per empty array.

    Chrome: memory footprint for the tab is 116,164K. Roughly the same overhead as Firefox.

So there you are: it looks like you get roughly 90 bytes of overhead per [], compared with using undefined or null.

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
2

var Arr1 creates a memory footprint that holds a reference to nothing. So, yes, there is a cost to this, but it is minimal.

But, var Arr2 = [] creates a memory address that is holding a reference to a new Array object, so there is more of a footprint there. Even though the array is empty, it is a unique instance of an Array object, which, itself uses the single Array.prototype to inherit from. It's the population of the Array that will really take up memory, since even a billion empty arrays don't have to store anything that is not already being stored by Array.prototype. Even with a billion empty arrays, they all inherit from just one Array.prototype object and that is where the native API for arrays is stored.

customcommander
  • 17,580
  • 5
  • 58
  • 84
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • nice explanation – 0.sh May 27 '17 at 22:18
  • The reason I asked is (coming from a C++ background) a billion instances of an object, even if empty, still take space in the stack, because each instance needs space to define itself and for its own private variables, etc. I am not sure how an array is implemented internally in Javascript and how many bytes it needs for each empty array instance variables. – Thomas An May 27 '17 at 22:21
  • The actual storage footprint will vary depending on the implementation. But, the process is similar, except that only the array elements and any additional properties you create will be stored with the new Arrays. All the basic functionality is stored just once in the prototype. – Scott Marcus May 27 '17 at 22:30
  • @ScottMarcus: Yes, it is not the prototype that worries me. It is how each instance is implemented in memory. So, if for example the array object uses a 'length' variable internally. A billion empty array instances will still each have a length variable (for a total of a billion variables) on top of the pointer variable for the location of the object instance. – Thomas An May 27 '17 at 22:41
  • Well, the `length` property is inherited and a billion instances will store a number in that inherited property. That's true. – Scott Marcus May 27 '17 at 22:42