11

What is the memory footprint of an empty object in JavaScript? If object is created using object literal syntax:

let emptyObj = {};

in Google Chrome Developer Tools (Profiles tab), after taking snapshot, it shows that Shallow Size as well as Retained Size is equal to 56 Bytes. Also, the same size is present if object is created by:

let emptyObj = Object.create(null);

For me, that's far too much, as I am creating a lot of objects (not necessarily empty, but mostly with only few properties) during code execution and I have to store them in memory. I am assuming that if it would be possible to decrease empty-object size, it would be also possible to decrease size of an object with properties by the same amount of Bytes.

For example, if object looks like this:

let foo = {bar: 4};

and it has the size of, let's say, 56 (empty object overhead) + 6 (key) + 8 (value) = 70 Bytes, then reducing size of an empty object by 40 Bytes would result foo having size of 30 Bytes (16 + 6 + 8).

Is this correct interpretation of Chrome's empty object size? Is it possible to decrease it? Would it result in decreasing size of not-empty object?

proxeld
  • 111
  • 5
  • 4
    "Is it possible to decrease it?" No. You have no control over to how the browser interprets the "create an object" operation and what it actually stores in your computer's memory to represent that. In general simply stop worrying about object sizes in JS, pages and web apps use literally hundreds if not thousands of them. Just don't forget to remove references to objects you no longer need and GC will do the rest. – Dimitris Karagiannis Oct 08 '16 at 12:24
  • The language specification ([*ECMA-262*](http://ecma-international.org/ecma-262/7.0/index.html)) does not define implementation, so the memory footprint likely differs between implementations. Creating an object with an object literal should return exactly the same result as creating it using the Object constructor. – RobG Oct 08 '16 at 12:26
  • @MitchKarajohn Unfortunately, I need to store millions of them and I cannot reduce that amount. So I try to figure out how to decrease the size of "base" of every object. That would give me huge memory gain. – proxeld Oct 08 '16 at 12:44
  • 1
    @proxeld just store them and see how your performance is affected. The optimisations you can make from there are among the lines of whether you should be really storing them all in memory or can you be creating them gradually, and to make sure you are making use of the GC by removing references to unused objects. Again, in general, don't worry about memory *too* much, unless you have really created a memory hog. I would worry more if I had to render the information contained in these millions of objects for some reason. – Dimitris Karagiannis Oct 08 '16 at 12:51
  • 1
    Did your objects have all the same properties, and all props are primitive types (int, float, boolean)? – pleup Oct 08 '16 at 12:51
  • @MitchKarajoh So, basically I store copy of the state of an application (very frequently) and I cannot remove any object from past that represents that state. Thus, this objects cannot be garbage-collected if I want to return to that state. – proxeld Oct 08 '16 at 12:54
  • Oh, yes, also what @pleup said: Check out [how JS stores to variables](http://stackoverflow.com/a/6605700/4651083). Things are not as bad as you might have imagined. – Dimitris Karagiannis Oct 08 '16 at 12:55
  • @pleup Mostly primitives, copied (not references), so things are bad :( – proxeld Oct 08 '16 at 12:56
  • What you described that you are doing reminded me of something like imutable states. Things are not so bad as you imagine, due to how JS stores to variables. [Take a look in this article](http://www.youhavetolearncomputers.com/blog/2015/9/15/a-conceptual-overview-of-redux-or-how-i-fell-in-love-with-a-javascript-state-container). Start reading from the "Consider your app state as a tree, with a root and child nodes." part, it's releveant to your case I think. Also [see this graphic](http://i.giphy.com/l41lRQkv8HjBo7nvW.gif), in case it helps you visualise this. – Dimitris Karagiannis Oct 08 '16 at 13:02
  • @MitchKarajohn Sadly, this also does not apply, since I am not developing web application with my own state and state-modification flow, but rather recording state that is modified by game engine. – proxeld Oct 08 '16 at 13:17
  • 1
    Maybe not so bad. It's can be a bit painfull to implement but you could store all your objects, flatten in a single array, are even better, preallocated ArrayBuffer. A bit like C _structs_ arrays are layed out when malloced. – pleup Oct 08 '16 at 13:20
  • 1
    @proxeld How about saving only diffs instead of the full state, and every like 100 entries you store a full state. Depending on how much your state is changing per iteration, this could reduce the memory footprint tremendously, and due to the "keyframes" you can recreate every single state in reasonable time. – Thomas Oct 08 '16 at 13:34
  • @Thomas Yes, I thought about it and I will definitely use this approach, but I also wanted to optimize it on even earlier stage (before diffing) if it's possible. But, it seems that it isn't. – proxeld Oct 08 '16 at 13:54

1 Answers1

-2

The empty object is not so empty. If you do emptyObj.__proto__ = null it will delete the __proto__ chain. But then it may throw errors for some basic methods of Object. However simple property assignments and property reads will work well. Hope it would save you some bytes.

Thevs
  • 3,189
  • 2
  • 20
  • 32
  • `__proto__` is not an own property of an object. You cannot `delete` it. If you don't understand how it works, please don't use it. And it's deprecated anyway. Use `Object.setPrototypeOf`/`Object.getPrototypeOf` instead. – Bergi Oct 09 '16 at 13:38
  • If you want a really empty object, just instantiate it using `Object.create(null)`. Don't mess with the prototype chain of existing objects. – Bergi Oct 09 '16 at 13:39
  • In any case, there's hardly a memory difference in object size between the [[prototype]] link pointing to `Object.prototype` and the [[prototype]] link pointing to `null`. – Bergi Oct 09 '16 at 13:40
  • Talent does what he knows, genius does what he wants. You CAN delete prototype chain in this particular case, to decrease amount of memory used. However if you delete `__proto__`, you cannot use some internal methods of object and you must know the consequences of this. – Thevs Oct 10 '16 at 06:26
  • @Bergi You'll never be a good Programmer if you don't dare to go around `taboos` and break the common rules. – Thevs Oct 10 '16 at 06:35
  • My point is knowing what you do not want. To start with, "*delete prototype chain to decrease amount of memory*" is totally wrong - even the OP measured that `{}` and `Object.create(null)` take the same amount of memory. And no, whether an object has a `__proto__` property or not has nothing to do with using "internal" methods (I assume you mean `Object.prototype` ones). You can `delete Object.prototype.__proto__` and everything will still work. – Bergi Oct 10 '16 at 10:16
  • Oh, I'm regularly breaking rules that are considered "common" because I know where they apply specifically and where they don't, or when a taboo is the only working solution. But in any case, one must point out the rules when someone who does not know what he is doing breaks them. And suggesting to break them in an SO answer for a clueless OP is never a good idea. – Bergi Oct 10 '16 at 10:19
  • @Thevs As Bergi mentioned, even after creating object without `prototype` payload it seems to have the same size in Google Chrome as object literal (`{}`). So setting `__proto__` to `null` won't help here. – proxeld Oct 11 '16 at 17:19
  • The key word here is 'it seems'. Have you measured it? – Thevs Oct 12 '16 at 14:31
  • Creating object without `prototype` (I don't know what Bergi had in mind) and setting `__proto__` to null are different things. Check it with profiler. – Thevs Oct 12 '16 at 14:48