13

Я видел некоторые производительности критически яваскрипт кода, как один на this project, что делает широкое использование побитового ИЛИ операции с 0. Ex:Что такое стиль asm «x | 0», который используют некоторые javascript-программисты?

GameBoyAdvanceCPU.prototype.write8 = function (address, data) { 
address = address | 0; 
data = data | 0; 
this.memory.memoryWrite8(address | 0, data | 0); 

Я знаю о прецеденте номеров напольных покрытий с «| 0 », но здесь это не так, поскольку они всегда являются int. Это немного похоже на asm.js, так это сказать движку js, что мы работаем с целыми числами, что позволяет некоторые оптимизации? Если да, то какие браузеры сделают эти оптимизации?

Любые указания на то, как это работает, будут рассмотрены.

+0

@RobG это не эквивалентно значению '4.2'. – zerkms

+2

Это стиль asm.js. Он приводит в соответствие значение с 32-разрядным целым числом, которое быстрее, чем с плавающей запятой. –

+0

@ RobG: И не для '3141592658'. – Bergi

ответ

-1

| Оператор - bitwise OR. Он используется для поэтапной операции ИЛИ на двух целых числах.

Использование здесь ярлыка очень похоже на логическое ИЛИ || оператору предоставлять значение по умолчанию, за исключением того, что результат является целым числом только (в отличие от строки ... и т.д.)

address = address | 0; 

означает «если адрес является числом, давайте использовать его, в противном случае, установите его 0" .

+0

Какой смысл делать это? Зачем предпочитать его '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' – zerkms

+0

@zerkms, я не уверен. Я могу только догадываться, может быть, они хотят убедиться, что это номер, поэтому он не нарушает код. Если адрес «foo», значение || не вступит в силу ... – BernieDADA

1

Что это на самом деле можно увидеть в этом fiddle

Это зондирование переменного против целого типа в этом случае и как «пол» или установите его в 0, если не является целым числом.

Таким образом, существует колоссальный отличий от a = a || 0, который оставил бы значение 3.2 нетронутым.

+0

Попробуйте '3141592658'. – Bergi

+0

@ Берги хм, интересно. Нужно еще несколько исследований ... –

3

Реферирование the Ecmascript 5 spec: 11.10 Binary Bitwise Operators, а именно

производства A : A @ B, где @ является одним из битовых операторов в на производство выше (&; ^; |), вычисляется по следующей схеме:

Пусть lref быть результатом оценки A.
lval be GetValue(lref).
rref be
Позволяет rval быть GetValue(rref).
lnum be ToInt32(lval).
rnum be ToInt32(rval).
Возврат результата применения побитового оператора @ к lnum и rnum. Результатом является подписанное 32-битное целое число.

И заметив, что ToInt32() is defined as

Пусть number быть результатом вызова ToNumber входного аргумента.
Если номер NaN, +0, −0, +∞, или −∞, возврат +0.
posInt be sign(number) * floor(abs(number)).
int32bit be posInt modulo 2^32; то есть конечное целое значение k типа Number с положительным знаком и менее 2^32 по величине, так что математическая разность posInt и k математически является целым числом, кратным 2^32.
Если int32bit больше или равно 2^31, возврат int32bit − 2^32, в противном случае возврат int32bit.

Затем логически следует (что вы можете подтвердить в своей собственной консоли), что, например

((Math.pow(2, 32)) + 2) | 0 === 2 
(Math.pow(2, 31)) | 0 === -2147483648 === -(Math.pow(2, 31)) 

И так далее.

В короткой позиции операция превращает число в 32-разрядное целое (которое имеет свои навыки, см. Второй пример выше и определение ToInt32() для объяснения), а затем делает логическое или с нулевым значением, которое не изменяется выход за пределы первого преобразования.

По сути, это очень рентабельный способ превратить число в 32-разрядное целое, поскольку 1) он полагается на встроенный браузер ToInt32(); и 2) ToInt32(0) замыкание на замыкание до 0 (см. выше спецификацию) и, следовательно, добавляет практически никаких дополнительных накладных расходов.

+1

+1, очень приятно. Меня все еще интересует угол оптимизации этого: зачем нужно, чтобы браузер вызывал toInt32, не так ли, что js-двигатели быстрее выполняют некоторые операции? –

+1

@DiogoFranco Когда я прокомментировал еще один ответ, я видел людей _claim_, он предлагает прирост производительности несколько раз, но я еще не видел, чтобы кто-нибудь демонстрировал код, где он на самом деле приводит к лучшей производительности, кроме использования его как преобразование, чтобы гарантировать, что параметры имеют заданный тип. Такие тесты, как [этот Jsperf, который я создал только сейчас] (http://jsperf.com/bitwise-or-0-performance), не показывают различимых различий в скорости (я пробовал несколько различных арифметических и логических операций с разными параметрами, не стесняйтесь экспериментировать самостоятельно). – Nit

+0

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

5

Согласно JavaScript Performance for Madmen

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

и в соответствии со страницей это верно для «самых» Javascript runtimes, но не говорит, что.

В качестве второго источника, Writing Fast JavaScript For Games & Interactive Applications состояния

Рассказывать двигатель JavaScript мы хотим хранить целые значения [...] мы могли бы использовать побитовое или оператор:

и третий источник из Microsoft's Writing efficient JavaScript page:

[...] явно указать время выполнения JavaScript, чтобы использовать целочисленную арифметику [...] использовать побитовое или оператора

Кроме того, в комментариях ни одна из приведенных выше страниц не упоминает asm.js, поэтому я подозреваю, что такие оптимизации применяются в коде, явно не помеченном как asm/в браузерах, которые явно не распознают его.

+0

Я встречался с претензиями несколько раз, но я еще не видел, чтобы кто-то действительно демонстрировал прямую прирост скорости везде, кроме быстрого преобразования. – Nit