05.01.2015, 03:05
|
|
|
Регистрация: 10.07.2008
Сообщений: 3,873
|
|
fix leaking arguments
Речь о том, чтобы никуда не передавать и не создавать ссылки на arguments, иначе выключаются оптимизации.
Пример:
function f1() {
f3(arguments);
}
function f2() {
var i = arguments.length;
var args = new Array(i);
while (i--) {
args[i] = arguments[i];
}
f3(args);
}
function f3(args) {
return args[0];
}
Как выяснилось по тестам http://jsperf.com/leaking-arguments/2 код с функцией f2 работает гораздо быстрее, не смотря на то, что выполняет лишние действия.
На mbp c core i5 2.4GHz:
- как не странно Chrome 41 показывается практически одинаковые результаты (хотя это как бы для V8 оптимизация https://github.com/petkaantonov/blue...ging-arguments)
- Firefox 35 в 5 раз быстрее!
- Safari 8 в 4 раза быстрее
- IE11 в 2 раза быстрее
Что-то я раньше не придавал этому большого значения, думал что это только для V8 актуально, а он и так быстрый, но как оказалось следует так делать для всех браузеров.
Последний раз редактировалось Octane, 05.01.2015 в 03:17.
|
|
05.01.2015, 07:56
|
|
Профессор
|
|
Регистрация: 24.09.2013
Сообщений: 1,436
|
|
Win7, intel core i3-2100 3.1GHz, Firefox 36 - в 16 раз быстрее
Последний раз редактировалось Erolast, 05.01.2015 в 08:19.
|
|
05.01.2015, 11:31
|
|
junior
|
|
Регистрация: 29.11.2011
Сообщений: 3,924
|
|
Octane, вторая функция разве не заменяется на это
Array.prototype.slice.call(arguments);
?
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Последний раз редактировалось nerv_, 05.01.2015 в 11:34.
|
|
05.01.2015, 15:17
|
|
|
Регистрация: 10.07.2008
Сообщений: 3,873
|
|
Сообщение от nerv_
|
вторая функция разве не заменяется на это
Array.prototype.slice.call(arguments);
?
|
Судя по руководству Optimization killers, безопасно передать arguments можно только в apply.
Цитата:
|
What is safe arguments usage?
Only use
• arguments.length
• arguments[i] where i is always a valid integer index into the arguments, and can not be out of bound
• Never use arguments directly without .length or [i] (STRICTLY x.apply(y, arguments) is ok, nothing else is, e.g. .slice. Function#apply is special)
And note that the FUD about mentioning arguments causing an allocation of the arguments object is untrue when you use the it in the mentioned safe ways.
|
ну и на тестах это подтверждается, вариант с slice.call самый медленный http://jsperf.com/leaking-arguments/3
Последний раз редактировалось Octane, 05.01.2015 в 15:28.
|
|
05.01.2015, 16:07
|
Профессор
|
|
Регистрация: 09.11.2014
Сообщений: 610
|
|
Octane,
То что ты пишешь, больше похоже на пляски с бубнами и заклинания. Толк от таких мизерных оптимизаций будет только один: ты запутаешь и усложнишь код, и твое приложение будет тормозить раз в сто сильней.
К тому же, ты сравниваешь теплое с мягким. Ты в одном случае передаешь в f3 объект, а в другом -- массив. Возможно твои "тормоза" по большей части связаны с извлечением по ключу из объекта. return args[0];
|
|
05.01.2015, 16:20
|
Профессор
|
|
Регистрация: 09.11.2014
Сообщений: 610
|
|
Octane,
вот объективное сравнние, из которого видно, что сам объект аргументс тут не причем. И он даже выигрывает в V8, кстати.
UPD в FF -- тоже
function f1() {
f3(arguments);
}
function f2(args) {
f3(args);
}
function f3(args) {
return args[0];
}
i=100000
console.time("f1")
while(i--) f1(1,2,3)
console.timeEnd("f1")
i=100000
console.time("f2")
while(i--) f2({0: 1, 1: 2, 2: 3})
console.timeEnd("f2")
Последний раз редактировалось krutoy, 05.01.2015 в 16:26.
|
|
05.01.2015, 16:31
|
sinistral
|
|
Регистрация: 28.03.2011
Сообщений: 5,418
|
|
Octane, хай. может быть поможет: ссылька
было бы круто заиметь окружение тестирования V8 в своих тестах, чтобы писать типа:
var lib = require('my-lib');
MUST_OPTIMIZE_NEXT_CALL('Передача числа');
lib.atan(45);
MUST_OPTIMIZE_NEXT_CALL('Передача строки'); // функция деоптимизируется. тест кинет ошибку здесь с сообщением "Передача строки"
lib.atan('ЙОЙО');
я вроде помню, во внутренних тестах V8 есть такой ужас(MUST_OPTIMIZE...), но как получить к этому доступ - хз
ну а чтобы конкретно ответить на твой вопрос, нужно качать dev версию v8 на линуксах, вызывать js код из него и смотреть лог движка. сейчас уже нельзя с уверенностью ничего сказать, ибо за год в движках могло многое измениться
вот причины деооптимизаций. там есть:
Код:
|
V(kAssignmentToParameterFunctionUsesArgumentsObject, \
"Assignment to parameter, function uses arguments object") |
а вот и место, где она кидается (hydrogen - это оптимизирующий движок в V8, если память не изменяет)
Код:
|
switch (var->location()) {
case Variable::CONTEXT: {
// Bail out if we try to mutate a parameter value in a function
// using the arguments object. We do not (yet) correctly handle the
// arguments property of the function.
if (current_info()->scope()->arguments() != NULL) {
// Parameters will be allocated to context slots. We have no
// direct way to detect that the variable is a parameter so we do
// a linear search of the parameter variables.
int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
if (var == current_info()->scope()->parameter(i)) {
Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
}
}
} |
сама Variable::CONTEXT
Код:
|
// An indexed slot in a heap context. index() is the variable index in
// the context object on the heap, starting at 0. scope() is the
// corresponding scope.
CONTEXT, |
и теперь стало ещё непонятней ...
мало того, что на вопрос не ответил, так и сам запутался
в общем, если кто завладеет D8 в V8, отпишите сюда о результатах пож)
Последний раз редактировалось melky, 05.01.2015 в 16:53.
|
|
05.01.2015, 16:48
|
|
|
Регистрация: 10.07.2008
Сообщений: 3,873
|
|
Сообщение от krutoy
|
запутаешь и усложнишь код
|
Что сложного в том чтобы взять за правило: "не передавать arguments и не создавать ссылок на arguments"?
Сообщение от krutoy
|
Возможно твои "тормоза" по большей части связаны с извлечением по ключу из объекта. return args[0];
|
Это понятно. После вопроса nerv_ я добавил следующий тест, где есть 2 варианта с передачей массива.
Последний раз редактировалось Octane, 05.01.2015 в 17:01.
|
|
05.01.2015, 17:07
|
|
|
Регистрация: 10.07.2008
Сообщений: 3,873
|
|
melky, по-моему процетированный тобой код про это
(function (a) {
arguments[0] = 2;
alert(a);
}(1));
|
|
05.01.2015, 17:23
|
Профессор
|
|
Регистрация: 09.11.2014
Сообщений: 610
|
|
Сообщение от Octane
|
не передавать arguments и не создавать ссылок на arguments
|
Я серьзено спрашиваю. Ты можешь сказать, каким образом в твоем коде тестируется передача arguments?
Вот мое видение твоего кода. Ты что-то куда-то передаешь, что абсолютно не важно, что и куда. А затем уже, в итоге, ты сравниваешь производительность доступа к ключу объекта с доступом по ключу массива. Причем тут arguments ты можешь четко сказать?
Если я напишу
[1][0] vs {0: 1}[0]
Это тоже будет проверка arguments?
|
|
|
|