是什么使这个函数运行得慢得多?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (38)

我一直在尝试做一个实验,看看函数中的局部变量是否存储在堆栈中。

所以我写了一个小小的性能测试

function test(fn, times){
    var i = times;
    var t = Date.now()
    while(i--){
        fn()
    }
    return Date.now() - t;
} 
ene
function straight(){
    var a = 1
    var b = 2
    var c = 3
    var d = 4
    var e = 5
    a = a * 5
    b = Math.pow(b, 10)
    c = Math.pow(c, 11)
    d = Math.pow(d, 12)
    e = Math.pow(e, 25)
}
function inversed(){
    var a = 1
    var b = 2
    var c = 3
    var d = 4
    var e = 5
    e = Math.pow(e, 25)
    d = Math.pow(d, 12)
    c = Math.pow(c, 11)
    b = Math.pow(b, 10)
    a = a * 5
}

我希望反转函数工作得更快。相反,一个惊人的结果出来了。

直到我测试其中一个函数,它的运行速度是测试第二个函数后的10倍。

例子:

> test(straight, 10000000)
30
> test(straight, 10000000)
32
> test(inversed, 10000000)
390
> test(straight, 10000000)
392
> test(inversed, 10000000)
390

同样的行为,当测试以替代顺序。

> test(inversed, 10000000)
25
> test(straight, 10000000)
392
> test(inversed, 10000000)
394

我已经在Chrome浏览器和Node.js上测试过它,我完全不知道为什么会发生这种情况。此效果持续到我刷新当前页面或重新启动NodeREPL为止。

是什么原因导致了如此显著的表现(大约要差12倍)?

提问于
用户回答回答于

一旦你调用两个不同的函数fn()测试,它内部的callsite变成了megamorphic。

o.m(...)V8中的函数调用(而不是方法调用)伴随着一个元素内联缓存,而不是真正的多态内联缓存。

由于V8无法在fn()调用站点内联,因此无法对你的代码应用各种优化。

V8只是内联straight删除了你希望通过Dead Code Elimination优化进行基准测试的所有代码。在V8的旧版本而不是DCE V8上,只需通过LICM将代码从循环中提取出来 - 因为代码完全是循环不变的。

何时straight不内联V8不能应用这些优化 - 因此性能差异。V8的新版本将仍然适用DCE到straightinversed自己把他们变成空函数

所以性能差异并不大(2-3倍左右)。

用户回答回答于

你误解了堆栈。

虽然“真正”的堆栈确实只有PushPop操作,但这并不适用于执行所用的堆栈。除了PushPop,你也可以随机访问任何变量,只要你有它的地址。在伪汇编中,你似乎认为

var x = 1;
var y = 2;

x = x + 1;
y = y + 1;

翻译成类似的东西

push 1 ; x
push 2 ; y

; get y and save it
pop tmp
; get x and put it in the accumulator
pop a
; add 1 to the accumulator
add a, 1
; store the accumulator back in x
push a
; restore y
push tmp
; ... and add 1 to y

事实上,真正的代码更像这样:

push 1 ; x
push 2 ; y

add [bp], 1
add [bp+4], 1

所属标签

可能回答问题的人

  • 嗨喽你好

    7 粉丝480 提问8 回答
  • uncle_light

    5 粉丝518 提问7 回答
  • Richel

    4 粉丝0 提问6 回答
  • 人生的旅途

    10 粉丝484 提问6 回答

扫码关注云+社区

领取腾讯云代金券