gpt4 book ai didi

javascript - 为什么 JavaScript 中的 Math.round 比自定义构建的函数慢?

转载 作者:行者123 更新时间:2023-12-03 12:46:55 25 4
gpt4 key购买 nike

我正在搞乱创建一个自定义舍入函数,该函数可以舍入到我想要的任何间隔。例如(如果我使用度数,它会四舍五入到最接近的 15 度) 无论如何,我决定看看它与 Math.round 相比有多快,然后发现它更慢。我在 FF8 上使用 Firebug

function R1(a,b){var c=a%b;return a-c+(c/b+1.5>>1)*b}

function R2(a){return Math.round(a)}

var i,e=1e5;
console.time('1');
i=e;
while(i--){
R1(3.5,1);
}
console.timeEnd('1');
console.time('2');
i=e;
while(i--){
R2(3.5);
}
console.timeEnd('2');

我的结果是
1: 464ms
2: 611ms

我以不同的方式运行了它们几次,但总是 R1 出来得更快。也许这只是 FF 的事情,但如果是这样,是什么原因造成的。

编辑:
我从函数调用中取出每一个,看看会发生什么
var i,e=1e5,c;
console.time('1');
i=e;
while(i--){
c=3.5%1;
3.5-c+(c/1+1.5>>1)*1;
}
console.timeEnd('1');
console.time('2');
i=e;
while(i--){
Math.round(3.5);
}
console.timeEnd('2');

和我得到的时间
1: 654ms
2: 349ms

最佳答案

简短的回答是,在 Firefox 8(但不是 9)中,Math.round 最终调用了一个 C++ 函数,这在 JIT 中很慢。长答案是它很复杂,并且在不同版本的 Firefox 中表现不同。此外,由于涉及 JIT,因此在不同的处理器和操作系统上会有所不同。

一点背景知识:根据 ECMA-262,Math.round 舍入到最接近的整数,除了 0.5,它朝 +Inf 舍入,对于 [-0.5, -0.0] 它舍入到 -0.0(IEEE-754 负零)。为了做到这一点,Math.round 必须做的不仅仅是 R1。它需要对四舍五入到 -0 的范围进行一些浮点比较(V8 会这样做),或者从输入中复制符号(SpiderMonkey 会这样做)。

现在,对于 Firefox 8,两个循环都由 tracejit 编译。对于带有 R1 的循环,R1 被内联并编译为纯 native 代码。 R2 被内联并编译为调用名为 js_math_round_impl 的 C++ 函数(在 js/src/jsmath.cpp 中)。

  • 调用任何函数都会产生额外费用,因为需要设置参数、进行调用、推送寄存器等。
  • 调用 Math.round 或类似的方法需要额外的费用,因为代码需要验证 Math.round 仍然是默认的 Math.round(即验证没有猴子补丁)。
  • 在 JIT 中调用 C++ 函数会产生额外费用,因为 JIT 不知道 C++ 函数使用什么寄存器,因此编译后的 JS 函数必须在调用之前存储所有调用者保存寄存器,然后再重新加载它们。该调用还可能清除其他假设,从而阻止其他优化。
  • 而且,如前所述,Math.round 必须比 R1 做更多的工作。

  • 我在 JS 和 C 中尝试了一些不同的测试,试图确定调用是否更重要,或者 -0 检查。结果各不相同,但看起来通话通常是放缓的主要原因(其中 70-90%)。

    在 Firefox 9 中,使用 JM+TI,R1 和 R2 的速度差不多。在这种情况下,R1 再次被内联(我认为)并编译为纯 native 代码。对于 R2,Math.round 由一段 jitcode 实现,该 jitcode 直接处理正数,但为负数(和 NaN 等)调用 C++ 函数。因此,对于给出的示例,两者都在 jitcode 中运行,而 R2 恰好要快一些。

    一般来说,对于像 Math.round 这样的函数(传统上是对 C++ 函数的调用,但足够简单,至少某些情况可以直接在 jitcode 中完成),性能很大程度上取决于多少引擎实现者为该特定功能所做的 jitcode 优化。

    关于javascript - 为什么 JavaScript 中的 Math.round 比自定义构建的函数慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8483357/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com