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

Снижение производительности для аргументов undefined

У меня довольно часто есть необязательные аргументы в функциях, но некоторые тесты показывают огромный успех для них в firefox и safari (70-95%). Как ни странно, если я пройду в буквальном значении undefined, то штраф не будет. Что может быть здесь? Я бы не подумал, что это проблема с цепочкой поставок, поскольку они по своей сути являются локальными для этой функции. Я должен начать передавать undefined в каждый необязательный аргумент?

jsPerf: http://jsperf.com/function-undefined-args/2

4b9b3361

Ответ 1

Для такой функции:

function threeArgs(x, y, z) {
  return x + y + z;
}

который называется так:

threeArgs(1, 2, 3);

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

Кроме того, если код был:

something += threeArgs(1, 2, 3);

оптимизатор может решить сгенерировать код, примерно эквивалентный:

something += 6;

Почему? Поскольку вызов был выполнен с числовыми константами, и он может безопасно сбрасывать их во время генерации кода. Это может быть консервативно, потому что цифры странные, но здесь они целые, поэтому вполне можно это сделать. Даже если этого не произошло, он мог бы безопасно встроить функцию:

something += 1 + 2 + 3;

Если отсутствует какой-либо параметр, возможно, оптимизаторы освобождают и генерируют реальный вызов функции. Для такой простой функции накладные расходы на вызов функции могут легко объяснить большую разницу в производительности.

Используя переменные вместо констант в тесте и фактически используя возвращаемое значение функции, вы можете "запутать" оптимизатор и не дать ему пропустить вызов или предварительно вычислить результат, но вы не можете держите его от наложения. Я по-прежнему считаю, что ваш результат интересен по этой причине: он раскрывает тот факт, что (на сегодняшний день в любом случае) эти оптимизаторы чувствительны к способу вызова этих функций.

Ответ 2

Я думаю, что может объяснить разницу в производительности, так как аргументы передаются объекту функции: через объект arguments. Если не передавать какие-либо аргументы, JS начнется с проверки объекта аргументов для любого из заданных аргументов, если они undefined, цепочка прототипов arguments будет отсканирована, вплоть до Object.prototype. Если все они не имеют желаемого свойства, JS вернет undefined. Принимая во внимание, что явно передавая undefined, он устанавливает его как свойство непосредственно в объекте arguments:

function foo(arg)
{
    console.log(arguments.hasOwnProperty('0'));
}
foo();//false'
foo('bar');//true
foo(undefined);//true

Я понимаю, что причина, по которой передача undefined явно имеет тенденцию быть быстрее.