Почему Javascript Math.floor является самым медленным способом вычисления пола в Javascript?

Я вообще не поклонник микрочипов. Но у этого есть очень интересный результат.
http://ernestdelgado.com/archive/benchmark-on-the-floor/

Это говорит о том, что Math.floor - это МЕДЛЕННЫЙ способ вычисления поля в Javascript. ~~n, n|n, n&n все быстрее.
Это кажется довольно шокирующим, так как я ожидаю, что люди, внедряющие Javascript в современных современных браузерах, будут довольно умными людьми.

Действительно ли пол делает что-то важное, что другие методы не могут сделать? Есть ли причина использовать его?

Ответ 1

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

Math.Floor должен учитывать множество различных сценариев обработки различных типов. Могли бы они сделать разные сценарии быстрее, выполняя короткие сокращения, как вы описали? Возможно, они могли, но это могло нарушить другие сценарии. Просто потому, что что-то на поверхности выглядит маленьким, не означает, что под ним нет айсберга.

Ответ 2

Основная причина Math.floor медленнее (где она на самом деле - в некоторых тестах, которые я делал это быстрее) заключается в том, что она включает вызов функции. Старые реализации JavaScript не могли встроить вызовы функций. Новые двигатели могут встроить вызов или, по крайней мере, ускорить поиск свойств, но они все равно нуждаются в защитном условии, если вы (или какой-то другой script) перезаписали функцию Math.floor. Накладные расходы минимальны, поэтому нет большой разницы в скорости.

Что еще более важно, хотя, как упоминалось в нескольких комментариях, другие методы не эквивалентны. Все они работают, выполняя поразрядные операции. Побитовые операторы автоматически преобразуют свои операнды в 32-битные целые числа, обрезая число. Это прекрасно, если число соответствует 32 битам, но номера JavaScript - это 64-битные поплавки, которые могут быть намного больше, чем 2147483647.

Они также дают другой результат для отрицательных чисел, так как преобразование в целые числа усекает и Math.floor всегда округляется. Например, Math.floor(-2.1) === -3, но (-2.1) | (-2.1) === -2.

Если вы знаете, вы имеете дело только с положительными номерами менее 2147483648, и вам нужно выжать каждый бит производительности из своего кода в старых браузерах (сначала убедитесь, что это узкое место. вероятно, нет.), я бы использовал еще более простой метод: x|0. Он не оценивает переменную дважды и работает, даже если x является выражением (просто не забудьте поместить его в круглые скобки, чтобы вы не сталкивались с проблемами приоритета).