JavaScript: выполнение одного и того же кода занимает разное время

Сначала я запускаю это (в хроме):

var start;
var end;

start = (new Date()).getTime();

for(var i=0;i<10e5;i++);

end = (new Date()).getTime();

console.log('delay:' + (end-start));

Вывод: delay:2028
Затем я запускаю это:

function foo() {
    var start;
    var end;

    start = (new Date()).getTime();

    for(var i=0;i<10e5;i++);

    end = (new Date()).getTime();

    console.log('delay:' + (end-start));
}

foo();

Вывод: delay:8

Почему тот же самый код занял меньше времени, когда был заключен в функцию?

В Node это заняло столько же времени (6 и 6), но Node использует движок V8 для Chrome, не так ли?


person Gergely Fehérvári    schedule 22.06.2012    source источник
comment
Для меня в Chrome оно варьируется между 1 и 2, 1 и 1, 2 и 1.   -  person James Allardice    schedule 22.06.2012
comment
вставьте свой код прямо в консоль. Я предполагаю, что jsfiddle выполняет какую-то обертку функций, и это портит пример.   -  person Gergely Fehérvári    schedule 22.06.2012
comment
О да, конечно! Игнорируй меня тогда. (в консоли получаю 897, 2).   -  person James Allardice    schedule 22.06.2012


Ответы (2)


Я думаю, что тот факт, что это поведение проявляется только в консоли, очень показателен. Я подозреваю, что это связано с тем, как движок V8 сокращает скрипт до собственного кода.

Вопрос 1. Я подозреваю, что область не является причиной замедления:

function foo() {
    start = (new Date()).getTime();
    for(i=0;i<10e5;i++);
    end = (new Date()).getTime();
    console.log('delay:' + (end-start));
}

Этот код использует start, end и i в глобальной области видимости. Если поиск по глобальной области видимости действительно был узким местом, то этот код тоже должен работать медленно, потому что у него нет локальных переменных в функции.

Вопрос № 2. Если вы поместите свой код на реальную веб-страницу, он будет работать очень быстро в любом случае. Это наводит меня на мысль, что причиной замедления является запуск кода в консоли.

Обычно на веб-странице движок V8 собирает JavaScript в собственный двоичный код, поэтому он работает очень быстро. Однако я подозреваю, что код, запускаемый из консоли, не компилируется (или, возможно, компилируется построчно по мере его запуска, что само по себе требует затрат времени). Однако при вводе определения функции функция полностью компилируется перед первым запуском. К тому времени, когда поток программы достигает вызова foo(), функция foo уже скомпилирована в машинный код. Таким образом, функция работает быстро, потому что она была предварительно скомпилирована, но необработанный код в консоли не был предварительно скомпилирован, поэтому она выполняется медленно.

В основном это предположения, но таковы и все ответы на этот вопрос. Это единственное объяснение, которое я могу придумать для обоих пунктов № 1 и № 2 выше.

person apsillers    schedule 22.06.2012
comment
Обычно на веб-странице собирается двигатель V8 - просто придирки... есть мир за пределами хрома :) - person rlemon; 22.06.2012
comment
@rlemon Я признаю, что иногда я виновен в том, что иногда немного ориентируюсь на Chrome (я изо всех сил стараюсь избавиться от привычки ... :)), но здесь ОП упомянул, что он наблюдает это поведение конкретно в Chrome (First i run this (in chrome)... ), поэтому я объясняю, почему такое поведение появилось именно в V8. - person apsillers; 22.06.2012
comment
и это предположение может объяснить, почему нет разницы в узле. - person Gergely Fehérvári; 22.06.2012

Потому что в функции все ваши переменные в замыкании. Без функции интерпретатора JavaScript попробуйте сначала найти ваши переменные в глобальной области видимости.

person antyrat    schedule 22.06.2012
comment
Я подозреваю, что это может быть не вся история. Если я перенесу объявления переменных start, end и i за пределы функции в глобальную область, я все равно увижу разницу в скорости. Если ваше объяснение верно (и я не говорю, что вы ошибаетесь!), почему разница в производительности все еще существует, когда все переменные являются глобальными? - person apsillers; 22.06.2012