2010-03-26 126 views
25

我一般不是microbenchmarks的粉丝。但这个有一个非常有趣的结果。
http://ernestdelgado.com/archive/benchmark-on-the-floor/为什么Javascript的Math.floor是计算Javascript中最慢的地方?

它暗示Math.floor是计算Javascript中最低层的方法。 ~~n,n|n,n&n一切都比较快。
这似乎相当令人震惊,因为我期望在当今现代浏览器中实现Javascript的人会是一些相当聪明的人。

地板是否做了其他方法无法做到的重要事情?有没有什么理由使用它?

+3

'~~ n','n | n'和'n&n'不会产生与Math.floor相同的结果。前三个只能返回32位整数。尝试'n = 50000000000.4'。 – kennytm 2010-03-26 21:00:12

+0

在我的浏览器(FF 3.6.something)中,结果的速度都是相同的(大约“3”,无论如何)。在不同的浏览器上尝试它(小测试在底部提供),而不仅仅是以面值为结果。真的没有理由为什么它会明显变慢。 – 2010-03-26 21:02:31

+3

实际上,他跑FF基准3.6表明'Math.floor'是最快的 – 2010-03-26 21:56:05

回答

26

它与现代浏览器无关。它与实施ECMA标准有关。即使有更快捷的方法,您也无法改变特定功能的执行方式。它可能会破坏现有的代码。

Math.Floor必须考虑很多处理不同类型的不同场景。如你所描述的那样,他们是否可以通过采取捷径来加快不同的情景?也许他们可以,但这可能会打破其他场景。仅仅因为表面上的东西看起来很小,并不意味着下面没有冰山。

+7

+1缓慢或没有,它可能是唯一正确的做法* – 2010-03-26 20:59:58

+1

好点。 'Math.floor(“foo”)'返回'NaN'。但如果这是我试图使用另一种方法的唯一好处。至少在Javascript支持整数除法之前。 – z5h 2010-03-26 21:01:35

+0

我不是说你应该总是使用Math.Floor,它很慢。只是当他们设计一个功能时,他们必须考虑到人们可能做的很多不同的场景。关于JS的一件事是,它意味着易于编程,这意味着在构建它时它们必须采取额外的预防措施,并且在某些情况下使它们走得很远。 – kemiller2002 2010-03-26 21:04:16

31

主要原因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是一个表达式(只要确保将其放在括号中,以避免遇到优先问题)即可使用。

+0

“JavaScript不能内联函数,因为它是动态的,您可以用不同的函数替换Math.floor。”这是一个无关紧要的问题。 JIT编译器可以并内联动态函数调用。跟踪JIT尤其擅长于此。活力通过警戒检查或添加失效触发来处理。具体的实现可能会或可能不会内联。正如所有微观优化一样,如果它确实很重要,请在目标平台上进行测量。 – 2010-03-29 16:23:44

+0

@Ants:好点。这就是我用缓存的函数值得到的,但我错误地写了它。 – 2010-03-29 18:09:26

+6

我知道这个答案已经过去几年了,但现在V8内联了函数调用,这导致了['Math.floor'表现得很差,并且按位分析黑客](http://jsperf.com/js-floors)。 – josh3736 2012-06-05 01:58:23

相关问题