Производительность побитовых операторов в javascript

Одна из основных идей использования побитовых операторов в таких языках, как C ++ / java / C #, заключается в том, что они очень быстрые. Но я слышал, что в javascript они очень медленные (по общему признанию, несколько миллисекунд, вероятно, сегодня не имеют большого значения). Почему это так?

(в этом вопросе обсуждается, когда используются побитовые операторы, поэтому я меняю фокус этого вопроса на производительность.)


person Gordon Gustafson    schedule 06.10.2009    source источник
comment
побитовые операции к этому моменту в разработке современных компиляторов не очень бывают быстрыми, если вы имеете в виду, что i ‹---------------- 1 быстрее, чем i * 2, в любом случае.   -  person Jimmy    schedule 06.10.2009
comment
@ Джимми: неважно, насколько продвинуты современные компиляторы, компиляторы 30 лет назад были достаточно умны, чтобы знать, что i ‹< 1 немного быстрее, чем i * 2 ... вы имеете в виду что-то более похожее к этому моменту в современных скоростях процессора, потому что разница в наносекунду на современных процессорах в значительной степени незначительна.   -  person Kip    schedule 11.10.2009


Ответы (12)


Когда бы вы хотели их использовать? Вы могли бы использовать их, когда хотите выполнять побитовые операции. Точно так же, как вы использовали бы логические операторы для выполнения логических операций и математические операторы для выполнения математических операций.

Если вы знакомы с побитовыми операторами, их вполне естественно использовать в некоторых приложениях. Их можно использовать для многих целей, кроме переоптимизированного логического массива. Конечно, эти обстоятельства не очень часто возникают при программировании на Javascript, но это не причина, по которой операторы не должны быть доступны.

person Kip    schedule 06.10.2009

Это довольно старый вопрос, но на обновленную версию, похоже, никто не ответил.

Падение производительности, которое вы получаете с помощью JavaScript, которого нет в C / C ++, - это приведение из представления с плавающей запятой (как JavaScript преобразовывает все свои числа) в 32-битное целое число для выполнения битовой манипуляции и обратно.

person Chad Schouggins    schedule 22.06.2012
comment
На самом деле это уже не так, учитывая, что большинство JS JIT отлично справляются с сохранением числа только в виде int, если с ним ничего не делается, что гарантирует операции с плавающей запятой. Хотя спецификация требует преобразований, реальные реализации должны работать по-другому, если конечный результат один и тот же. - person Joey; 14.09.2016
comment
Действительный момент, однако это все еще относится к заданному вопросу. - person Chad Schouggins; 30.09.2016

Никто больше не пользуется заклятием?

function hextoRgb(c) {
    c = '0x' + c.substring(1);
    return [(c >> 16) & 255, (c >> 8) & 255, c & 255]; 
}

var c1 = hextoRgb('#191970');
alert('rgb(' + c1.join(',') + ')');
person kennebec    schedule 06.10.2009
comment
На самом деле смещение струн мне кажется немного странным. Но с другой стороны, это легче читать, чем например return /#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i.exec(c).slice(1).map(function(e) {return parseInt(e, 16);});. - person Robert; 11.07.2013
comment
@Robert - это может выглядеть странно, но это будет намного быстрее, чем предложенная вами функция, поскольку у вас есть регулярные выражения, циклы и замыкания - person newshorts; 23.05.2017

Я использую побитовый сдвиг нуля в JS для быстрого целочисленного усечения:

var i=3.141532;
var iTrunc=i>>0; //3
person spender    schedule 06.10.2009
comment
Это действительно отвратительное использование оператора битового сдвига. - person Greg Hewgill; 06.10.2009
comment
Да, это грязно, я знаю, но на самом деле это нашло свое место в программировании игр для Flash. Во времена AVM1 это был самый быстрый способ. Не знаю, верно ли это для JS. - person spender; 06.10.2009
comment
var iTrunc = я | 0; экономит вам один удар в гольф (видел это в какой-то ветке кода для гольфа здесь) - person Jimmy; 06.10.2009
comment
-1 Очень-очень некрасиво. Программирование - это заставить других программистов понять, что вы делаете, а НЕ явно запутывать то, что вы пытаетесь сделать. - person Tomas; 13.08.2010
comment
+1 Программирование - это обеспечение того, чтобы программист и компьютер понимали, что вы делаете, и идиомы идеально подходят, если эти условия выполняются. Они есть во всех языках, даже в английском. Поначалу идиомы могут быть незнакомыми, но пока они (1) запоминаются и (2) поддаются определению, они полностью уместны в лексиконе программиста. - person Plynx; 21.05.2011
comment
Я думаю, вы должны понимать, что это игровое программирование, и такие вещи обычны и необходимы. Тем не менее, неплохо иметь хорошую документацию, объясняющую тактику производительности для вашего проекта. Вы должны увидеть некоторые обручи, необходимые для минимизации сборки мусора в JVM. - person martyman; 25.02.2012
comment
На самом деле это неплохая идея, но комментарий кода будет хорошей идеей, если вы не на 100% уверены, что ваша аудитория поймет ваше намерение. - person Neil; 22.11.2013
comment
Обратите внимание, что это не только усечет число до его целой части, но и усечет его до 32-битного значения со знаком. Вы также можете использовать >>> для усечения до 32-битного значения без знака. - person hippietrail; 17.12.2017

Я нашел полезную информацию @ http://dreaminginjavascript.wordpress.com/2009/02/09/bitwise-byte-foolish/

Судя по всему, в наши дни они выступают очень хорошо. Зачем вам их использовать? По той же причине, что и где-нибудь еще.

person snarf    schedule 06.10.2009
comment
Я на 3 года опаздываю на вечеринку, но спасибо за ссылку на хорошее чтение =) - person aschyiel; 03.09.2012
comment
@aschyiel ну, я опоздал на 10 лет .. вечеринка все еще продолжается? - person J.G.Sebring; 12.02.2019

Существует эмулятор NES, написанный на JavaScript - кажется, он много использует побитовые операции.

person nobody    schedule 06.10.2009

Я думаю, что разработчик должен сделать оператора эффективным или неэффективным. Например, нет ничего, что мешало бы разработчику JavaScript создать виртуальную машину JITting, которая превращает поразрядную операцию в 1 машинную инструкцию. Так что нет ничего изначально медленного в «побитовых операторах в JavaScript».

person Jonathan Feinberg    schedule 06.10.2009
comment
@Snarfblam эта «теория» улучшения реализаций JavaScript имеет множество практических прецедентов в короткой истории JavaScript. Кроме того, и я не уверен, что это тоже точка зрения eecoli, все процессоры поддерживают быструю побитовую операцию, поэтому действительно нет ничего изначально медленного в побитовой операции на этом низком уровне, поэтому, если по какой-то причине реализация javascript небрежно не смогла сопоставить побитовые операции js этим эффективным машинным операциям, это можно было бы легко исправить и быстрее, если бы были какие-либо признаки того, что эта проблема эффективно является узким местом для большинства применений js. - person mjv; 06.10.2009

Я сомневаюсь, что побитовые операции особенно медленны в javascript. Поскольку такие операции могут напрямую отображаться на операции ЦП, которые сами по себе достаточно эффективны, похоже, что у побитовых операций нет какой-либо неотъемлемой характеристики, которая заставила бы их быть непоправимо медленными в javascript.
Редактировать декабрь 2015 г.: я исправлюсь! Падение производительности, которое испытывает Javascript в отношении побитовых операций, происходит из-за необходимости преобразования из числа с плавающей запятой в int и обратно (поскольку все числовые переменные в Javascript хранятся как значения с плавающей запятой). Спасибо Чаду Шуггинсу за указание на это.

Тем не менее, как указано в нескольких ответах, существуют различные приложения javascript, которые полагаются на побитовые операции (например, криптография и графика) и которые не особенно медленные ... (см. Silky и Snarfblam на этой странице). Это говорит о том, что, хотя они и медленнее, чем C / C ++ и другие языки, которые напрямую переводят побитовые операции в отдельные собственные инструкции ЦП, побитовые операции все так же медленны.

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

Несмотря на то, что javascript использовался для других целей, этот язык чаще всего используется для предоставления услуг пользовательского интерфейса.
Кстати, я вовсе не имею в виду это уничижительно; выполнение этих интеллектуальных функций пользовательского интерфейса и с учетом различных ограничений, налагаемых на язык, а также слабого соблюдения стандартов, требовало - и продолжает требовать - талантливых хакеров javascript.
Дело в том, что в контексте требований к типу пользовательского интерфейса необходимость в количестве побитовых операций, которые могут выявить медлительность javascript в обработке таких операций, в лучшем случае является редкостью. Следовательно, для типичного использования программисты должны использовать побитовые операции там, где и если этот подход кажется хорошо сочетающимся с общей программой / данными, и они должны делать это, не заботясь о проблемах с производительностью. В маловероятном случае производительности. узкое место, возникающее из-за побитового использования, всегда можно реорганизовать, но лучше держаться подальше от ранней оптимизации.

Заметным исключением из вышеизложенного является введение canvas в современных браузерах, мы можем ожидать, что от хостов javascript потребуются более примитивные графические функции, а такие операции могут потребовать в некоторых случаях больших доз побитовые операции (а также здоровые математические функции). Вполне вероятно, что эти службы в конечном итоге будут поддерживаться с помощью библиотек javascript (и даже в конечном итоге будут добавлены к языкам). Для таких библиотек будут использованы общие знания отрасли, чтобы найти наиболее эффективные подходы. Кроме того, и если действительно есть слабость в производительности javascript с побитовыми операциями, мы получим некоторую помощь, поскольку я предсказываю, что реализации javascript на различных хостах (браузерах) будут изменены для улучшения этой конкретной области. . (Это будет следовать типичной схеме развития javascript, которую мы наблюдали на протяжении многих лет.)

person mjv    schedule 06.10.2009

Люди делают интересные вещи на JavaScript.

Например, в нем реализовано множество алгоритмов криптографии (по разным причинам); поэтому, конечно, используются побитовые операторы.

person Noon Silk    schedule 06.10.2009

Используя JavaScript в его инкарнации Windows Scripting Host JScript, у вас может возникнуть необходимость использовать побитовые операторы для выбора флагов в значениях, возвращаемых из вызовов WMI или Active Directory. Например, значение User Access для записи пользователя в AD содержит несколько флагов, упакованных в одно длинное целое число.

ADS_UF_ACCOUNTDISABLE = 0x00000002;

if (uac & ADS_UF_ACCOUNTDISABLE == ADS_UF_ACCOUNTDISABLE) {
  // user account has been disabled
}

Или чья-то произвольная структура таблицы может содержать такое поле, доступное через ADO с JScript.

Или вы можете захотеть преобразовать некоторые извлеченные данные в двоичное представление на любой платформе только потому, что:

BinaryData = "L";
BinaryString = BinToStr(BinaryData, ".", "x");

// BinaryString => '.x..xx..'

Таким образом, есть множество причин, по которым может потребоваться манипуляция с битами в JavaScript. Что касается производительности, единственный способ узнать это - написать и протестировать. Я подозреваю, что в большинстве случаев это было бы вполне приемлемо, не намного хуже, чем любая другая из множества недостатков, содержащихся в этих системах.

person Todd    schedule 06.10.2009

Когда скорость имеет первостепенное значение, вы можете использовать их для битовой маскировки: http://snook.ca/archives/javascript/storing_values/

Кроме того, если вам нужно поддерживать Netscape 4, вы должны использовать их для работы с Document.captureEvents (). Не то, чтобы какая-либо респектабельная компания попросила вас писать JS для NS4 ...

person splicer    schedule 06.10.2009
comment
Добро пожаловать в ад. у вас есть два выбора для ваших вечных страданий: сжечь на угольном гриле или написать JS для NS4. - person Stefano Borini; 06.10.2009

Здесь проводится тестирование множества побитовых операций: http://jsperf.com/rounding-numbers-down/3

Однако не стесняйтесь создавать свои собственные тесты производительности на jsPerf!

person Mathias Bynens    schedule 07.08.2010