Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does creating functions consume more memory

// Case A
function Constructor() {
  this.foo = function() {
    ...
  };
  ...
}

// vs 
// Case B
function Constructor() {
  ...
};

Constructor.prototype.foo = function() {
  ...
}

One of the main reasons people advise the use of prototypes is that .foo is created once in the case of the prototype where as this.foo is created multiple times when using the other approach.

However one would expect interpreters can optimize this. So that there is only one copy of the function foo in case A.

Of course you would still have a unique scope context for each object because of closures but that has less overhead then a new function for each object.

Do modern JS interpreters optimise Case A so there is only one copy of the function foo ?

like image 608
Raynos Avatar asked Sep 16 '11 23:09

Raynos


People also ask

Do classes take up memory?

In general a class or struct is a concept and does not occupy variable (data) space, but it does take up memory in the compiler's memory. If a class or struct has methods, those methods will take up code space, if the methods are executed (linkers tend to drop functions that are not used).

How functions are stored in memory?

This is because in machine code, a function is referenced by its location in RAM, not its name. The compiler-output object file may have a func entry in its symbol table referring to this block of machine code, but the symbol table is read by software, not something the CPU hardware can decode and run directly.


1 Answers

Yes, creating functions uses more memory.

... and, no, interpreters don't optimize Case A down to a single function.

The reason is the JS scope chain requires each instance of a function to capture the variables available to it at the time it's created. That said, modern interpreters are better about Case A than they used to be, but largely because the performance of closure functions was a known issue a couple years ago.

Mozilla says to avoid unnecessary closures for this reason, but closures are one of the most powerful and often used tools in a JS developer's toolkit.

Update: Just ran this test that creates 1M 'instances' of Constructor, using node.js (which is V8, the JS interpreter in Chrome). With caseA = true I get this memory usage:

{
    rss: 212291584,       //212 MB
    vsize: 3279040512,    //3279 MB
    heapTotal: 203424416, //203 MB
    heapUsed: 180715856   //180 MB
}

And with caseA = false I get this memory usage:

{
    rss: 73535488,       //73 MB
    vsize: 3149352960,   //3149 MB
    heapTotal: 74908960, //74 MB
    heapUsed: 56308008   //56 MB
}

So the closure functions are definitely consuming significantly more memory, by almost 3X. But in the absolute sense, we're only talking about a difference of ~140-150 bytes per instance. (However that will likely increase depending on the number of in-scope variables you have when the function is created).

like image 148
broofa Avatar answered Sep 20 '22 11:09

broofa