在 C++/java/C# 等语言中使用位运算符的主要思想之一是它们非常快。但是我听说在 javascript 中它们非常慢(诚然,今天几毫秒可能并不重要)。为什么会这样?
(这个问题讨论了何时使用按位运算符,所以我将这个问题的重点转移到性能上。)
在 C++/java/C# 等语言中使用位运算符的主要思想之一是它们非常快。但是我听说在 javascript 中它们非常慢(诚然,今天几毫秒可能并不重要)。为什么会这样?
(这个问题讨论了何时使用按位运算符,所以我将这个问题的重点转移到性能上。)
这是一个相当古老的问题,但似乎没有人回答更新版本。
C/C++ 中不存在的 JavaScript 对性能的影响是从浮点表示(JavaScript 如何存储其所有数字)转换为 32 位整数以执行位操作并返回。
没人再用十六进制了吗?
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(',') + ')');
我在 JS 中使用零位移位来执行快速整数截断:
var i=3.141532;
var iTrunc=i>>0; //3
您想什么时候使用它们?当您想要进行按位运算时,您会想要使用它们。就像您使用布尔运算符进行布尔运算,使用数学运算符进行数学运算一样。
如果您对位运算符感到满意,那么将它们用于某些应用程序是很自然的。除了过度优化的布尔数组之外,它们还可以用于许多目的。当然,这些情况在 Javascript 编程中并不经常出现,但这并不是运算符不可用的原因。
我发现了一些很好的信息@http ://dreaminginjavascript.wordpress.com/2009/02/09/bitwise-byte-foolish/
显然,他们这些天的表现非常好。你为什么要使用它们?同样的原因,你会在其他任何地方。
有一个用 JavaScript 编写的NES 模拟器——它似乎大量使用了按位运算。
我认为由实施者来决定运营商是否高效。例如,没有什么可以阻止 JavaScript 实现者制作 JITting VM,它将按位操作转换为 1 条机器指令。因此, “JavaScript 中的位运算符”本质上并不慢。
我怀疑按位运算在 javascript 中特别慢。由于此类操作可以直接映射到 CPU 操作,这些操作本身非常高效,因此按位操作似乎没有任何固有特征会迫使它们在 javascript 中变得不可挽回地缓慢。
2015 年 12 月编辑:我的立场得到纠正!Javascript 在按位运算方面遭受的性能损失来自需要从浮点数转换为 int 并返回(因为 Javascript 中的所有数字变量都存储为浮点值)。感谢 Chad Schouggins 指出这一点。
尽管如此,正如在几个回复中所指出的那样,存在各种依赖于按位运算的 javascript 应用程序(例如:密码学和图形学)并且不是特别慢......(请参阅此页面上的 Silky 和 Snarfblam)。这表明,虽然比 C/C++ 和其他将按位运算直接转换为单个本地 CPU 指令的语言要慢,但按位运算却非常缓慢。
让我们永远不要考虑以下可能性,即某些特殊原因导致 javascript 主机的各种实现者以一种使这些操作极其缓慢的方式实现按位操作,看看这是否重要......
尽管 javascript 已被用于其他目的,但这种语言最常见的用途是提供用户界面类型的服务。
顺便说一句,我根本没有任何贬义的意思。执行这些智能 UI 功能,并考虑对语言施加的各种限制以及对标准的松散遵守,需要 - 并且一直需要 - 有才华的 javascript 黑客。
关键是,在 UI 类型要求的上下文中,对任何数量的位操作的需求可能会暴露 javascript 在处理此类操作时的缓慢性,这种情况充其量是不常见的。因此,对于典型用途,程序员应该使用按位运算,如果这种方法似乎可以很好地处理整个程序/数据,并且他们应该在不关心性能问题的情况下这样做。 在不太可能因按位使用而出现性能瓶颈的情况下,总是可以重构事物,但最好不要在早期优化中保持清醒。
上述值得注意的例外是canvas的引入,在现代浏览器上,我们可以预期 javascript 主机将需要更原始的图形功能,并且此类操作在某些情况下可能需要大量的位运算(以及健康数学函数)。很可能这些服务最终将通过 javascript 库的方式得到支持(甚至最终作为语言添加)。对于这样的图书馆,行业的共同智慧将被用来找出最有效的方法。此外,如果确实,按位运算的 javascript 性能存在弱点,我们会得到一些帮助,因为我预测将修改各种主机(浏览器)上的 javascript 实现以改进这一特定领域。(这将遵循我们多年来看到的典型的 javascript 演变模式。)
人们在 JavaScript 中做有趣的事情。
例如,其中实现了很多密码算法(出于各种原因);所以当然使用按位运算符。
在其 Windows Scripting Host JScript 化身中使用 JavaScript,您可能需要使用按位运算符来挑选从 WMI 或 Active Directory 调用返回的值中的标志。例如,AD 中用户记录的 User Access 值包含多个标志,这些标志打包成一个长整数。
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 中进行位操作的原因有很多。至于性能,唯一知道的方法就是编写它并测试它。我怀疑在大多数情况下它是完全可以接受的,不会比这些系统所包含的众多低效率中的任何其他情况更糟糕。
当速度至关重要时,您可以将它们用于位掩码:http ://snook.ca/archives/javascript/storing_values/
此外,如果您需要支持 Netscape 4,您可以使用它们来处理 Document.captureEvents()。并不是说任何受人尊敬的公司都会让你为 NS4 编写 JS ......
很多按位运算都在这里进行了基准测试:http: //jsperf.com/rounding-numbers-down/3
但是,请随意在 jsPerf 上创建自己的性能测试用例!