Почему в Javascript Math.floor самый медленный способ подсчета пола в Javascript?
Я вообще не фанат микробенчмарков. Но у этого есть очень интересный результат.
http://ernestdelgado.com/archive/benchmark-on-the-floor/
Это говорит о том, что Math.floor
это МЕДЛЕННЫЙ способ расчета пола в Javascript. ~~n
, n|n
, n&n
все быстрее.
Это кажется довольно шокирующим, так как я ожидаю, что люди, реализующие Javascript в современных современных браузерах, будут довольно умными людьми.
Пол делает что-то важное, что другие методы не могут сделать? Есть ли причина использовать его?
2 ответа
Это не имеет ничего общего с современными браузерами. Это связано с внедрением стандарта ECMA. Вы не можете просто изменить работу определенной функции, даже если есть более быстрый путь. Это может сломать существующий код.
Math.Floor должен учитывать множество различных сценариев обработки разных типов. Могли ли они сделать разные сценарии быстрее, используя короткие пути, как вы описали? Может быть, они могли, но это могло нарушить другие сценарии. То, что что-то на поверхности выглядит маленьким, не означает, что под ним нет айсберга.
Основная причина Math.floor
медленнее (где это на самом деле - в некоторых тестах, которые я сделал, это быстрее), что это включает вызов функции. В старых реализациях JavaScript не было встроенных вызовов функций. Более новые механизмы могут встроить вызов или, по крайней мере, ускорить поиск свойства, но им все равно необходимо условие защиты на случай, если вы (или какой-либо другой сценарий) перезаписали Math.floor
функция. Затраты минимальны, поэтому разница в скорости невелика.
Что еще более важно, хотя, как было упомянуто в нескольких комментариях, другие методы не эквивалентны. Все они работают, выполняя побитовые операции. Битовые операторы автоматически преобразуют свои операнды в 32-битные целые числа, усекая число. Это нормально, если число умещается в 32 бита, но числа JavaScript являются 64-битными числами с плавающей запятой, которые могут быть намного больше, чем 2147483647.
Они также дают другой результат для отрицательных чисел, поскольку преобразование в целые числа Math.floor
всегда округляется. Например, Math.floor(-2.1) === -3
, но (-2.1) | (-2.1) === -2
,
Если вы знаете, что имеете дело только с положительными числами, меньшими 2147483648, и вам нужно выжать каждый бит производительности из своего кода в старых браузерах (сначала убедитесь, что это на самом деле узкое место. Вероятно, нет), я бы использовал еще более простой метод: x|0
, Он не оценивает переменную дважды, и работает, даже если x
является выражением (просто не забудьте поставить его в скобках, чтобы избежать проблем с приоритетом).