Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this huge performance difference for an encapsulated Javascript function?

Tags:

So I have this simple code:

function Run () {
  var n = 2*1e7;
  var inside = 0;
  while (n--) {
    if (Math.pow(Math.random(), 2) +
        Math.pow(Math.random(), 2) < 1)
      inside++;
  }

  return inside;
}

var start = Date.now();
Run();
console.log(Date.now() - start);

And it will output some time around 335ms. That's pretty good. But, if I encapsulate the Run function like this:

var d = Date.now();
(function Run () {
  var n = 2*1e7;
  var inside = 0;
  while (n--) {
    if (Math.pow(Math.random(), 2) +
        Math.pow(Math.random(), 2) < 1)
      inside++;
  }

  return inside;
})();
console.log(Date.now() - d);

It will output 18319ms, which is much worse than the case before. Why is this ?

Also, if it matters, I'm running it on Chrome 26.0.1410.63, in the console. On node.js both snippets perform well on the console.

like image 816
João Pinto Jerónimo Avatar asked Dec 03 '13 15:12

João Pinto Jerónimo


People also ask

How does encapsulation work in JavaScript?

Encapsulation, one of the principles of Object-Oriented Programming is the key to achieve such goals. By definition Encapsulation in JavaScript is a process of binding the data with the functions which act upon the data. Encapsulation allows us to control and validate the data. In JavaScript, variables resemble data.

Does JavaScript support encapsulation?

Of course, as the functional crowd knows, JavaScript has supported real data encapsulation all along. It's very easy to declare private data in JavaScript.

Is closure an encapsulation?

A closure is an example of encapsulation: it encapsulates the body of code together with the lexical scope. The only means of access into the capsule is through the function: the function is like a "method", and the elements of the captured lexical environment are like "slots" in an object.


1 Answers

There is no difference with function decleration and function expressions WRT to optimization, that would be ridiculous.


Console code in Google Chrome is wrapped in with statement like this:

 with ((console && console._commandLineAPI) || {}) {
      //Your code is concatenated here
 }

Because function declarations are hoisted, the former code will be effectively this:

function Run () {
  var n = 2*1e7;
  var inside = 0;
  while (n--) {
    if (Math.pow(Math.random(), 2) +
        Math.pow(Math.random(), 2) < 1)
      inside++;
  }

  return inside;
}

with ((console && console._commandLineAPI) || {}) {
  var start = Date.now();
  Run();
  console.log(Date.now() - start);
}

So the declaration is running outside with statement. In fact it is not valid syntax to have function declaration in a block, function declaration can only be a top level statement.

So anyway because of historical reasons V8 is nice and hoists it out instead of throwing syntax error:

var i = 3;

with({i:4}) {
    function test() {
        console.log(i);
    }
}
test();//logs 3 so it is obviously **not** under `with` influence

So because the declaration is not under with statement, it will run much faster. With statement is not optimizable* under V8 and also breaks lexical scoping.


*Not optimizable means the optimizing compiler will not look at the code instead only the generic compiler will generate code for the function. It is comparable to firefox's interpreter vs JIT mode. If you wish to know more about what language features disable optimization in V8, read optimization killers

like image 130
Esailija Avatar answered Sep 23 '22 15:09

Esailija