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

Почему неисполненные утверждения замедляют мои функции?

Я создал четыре различные функции, например:

var normal = function() {
    return;
};
var control = function() {
    return;
    alert("Hello, world!");
};
var withArguments = function() {
    return;
    arguments;
};
var withEval = function() {
    return;
    eval("");
};

Поскольку все они просто ничего не делают и сразу возвращаются, я ожидаю, что все они будут иметь одинаковую скорость. Но после тестирование на jsPerf, я обнаружил, что normal и control выполняются примерно одинаково, но withArguments и withEval выполняются гораздо медленнее.

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

4b9b3361

Ответ 1

Короче говоря, вызов eval внутри функции и возможность доступа к массиву arguments используют дополнительную настройку во время вызова функции. Если известно, что ни arguments, ни eval не будут выполнены, эта дополнительная настройка может быть пропущена.

Компилятор не пытается предсказать, действительно ли будет иметься доступ к массиву arguments или действительно ли будет вызван eval, он проверяет, существуют или нет они в функции.

arguments

Во время выполнения во время выполнения более дорого вызывается переменная функция, которая использует объект arguments, чем "нормальная" функция, которая не использует объект arguments.

Дополнительные шаги, необходимые для привязки среды выполнения при объявлении объекта arguments: указанные в §10.6 стандарта ECMA-262, Создание объекта arguments - несколько дорогостоящий 15-ступенчатый процесс. В принципе, arguments должен быть заполнен аргументами с передачей, а свойства .caller и .callee должны быть созданы.

В стандарте указано, что объект arguments должен быть создан, когда функция входит в контекст выполнения, если в функции с именем arguments уже нет параметра, переменной или функции.

В целях оптимизации большинство браузеров фактически не создают объект arguments, если функция фактически не использует его где-нибудь (даже после return). Вот почему вы видите удар производительности, когда arguments ссылается, даже если строки, содержащие его, никогда не выполняются.

eval

Ввод eval кода, поскольку указанный в §10.4.2 стандарта ECMA-262, требует создания специального контекста выполнения. В основном, он должен привязать все свойства контекста выполнения вызывающей функции к контексту eval.

Если в одной функции вызывается несколько eval, они будут в основном выполнять один и тот же процесс дважды. Для оптимизации, если браузеры обнаруживают, что есть функция eval в функции (даже после return), она предварительно заполняет этот новый контекст выполнения, который может использовать каждый eval, так что ему не нужно воссоздан несколько раз.


Обратите внимание, что эти оптимизации зависят от браузера и не требуются стандартным, поэтому некоторые браузеры могут не выполнять описанные оптимизации, иначе они могут делать что-то по-другому.