Подтвердить что ты не робот

Почему эта огромная разница в производительности для инкапсулированной функции Javascript?

Итак, у меня есть этот простой код:

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);

И он выведет некоторое время около 335 мс. Это очень хорошо. Но если я инкапсулирую функцию Run следующим образом:

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);

Он выведет 18319мс, что намного хуже, чем раньше. Почему это?

Кроме того, если это имеет значение, я запускаю его на Chrome 26.0.1410.63 в консоли. В node.js оба фрагмента хорошо работают на консоли.

4b9b3361

Ответ 1

Нет никакой разницы с выражением функции и выражениями функций WRT для оптимизации, что было бы смешно.


Консольный код в Google Chrome заключен в оператор with следующим образом:

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

Поскольку объявления функций поднимаются, первый код будет эффективно:

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);
}

Таким образом, в объявлении выполняется внешний with. На самом деле недопустимый синтаксис для объявления функции в блоке, Объявление функции может быть только выражением верхнего уровня.

Так или иначе, из-за исторических причин V8 хорош и поднимает его, а не бросает синтаксическую ошибку:

var i = 3;

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

Итак, поскольку декларация не находится в with, она будет работать намного быстрее. С выражением не оптимизируется * под V8, а также ломается лексическое охват.


* Не оптимизируемый означает, что оптимизирующий компилятор не будет смотреть на код, а только генерирующий компилятор будет генерировать код для функции. Это сопоставимо с интерпретатором firefox и JIT. Если вы хотите узнать больше о том, какие функции языка отключить оптимизацию в V8, прочитайте оптимизаторы-убийцы