首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >是什么让这个函数运行得更慢呢?

是什么让这个函数运行得更慢呢?
EN

Stack Overflow用户
提问于 2015-07-29 18:46:59
回答 1查看 6K关注 0票数 64

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

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

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中测试过了,我完全不知道为什么会发生这种情况。这个效果会一直持续到我刷新当前页面或者重启Node REPL。

性能如此显著(~12倍)的原因可能是什么?

PS。因为它似乎只在某些环境下工作,所以请编写你用来测试它的环境。

我的是:

操作系统: Ubuntu 14.04

节点v0.10.37

Chrome 43.0.2357.134 (官方版本)(64位)

/Edit

在Firefox39上,无论顺序如何,每次测试都需要大约5500毫秒。它似乎只发生在特定的引擎上。

/Edit2

将函数内联到测试函数会使其始终在同一时间运行。

如果函数总是同一个函数,有没有可能存在内联函数参数的优化?

EN

回答 1

Stack Overflow用户

发布于 2015-07-29 19:22:28

你误解了堆栈。

虽然“真正的”堆栈确实只有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

如果线程堆栈真的是一个真正的、严格的堆栈,这是不可能的。在这种情况下,操作和局部变量的顺序将比现在更重要。相反,通过允许随机访问堆栈上的值,可以为编译器和CPU节省大量工作。

为了回答你的实际问题,我怀疑这两个函数实际上都没有做任何事情。您只需要修改局部变量,并且您的函数不会返回任何内容-编译器完全可以删除函数体,甚至可能删除函数调用。如果确实如此,那么您观察到的任何性能差异可能只是一个度量工件,或者与调用函数/迭代的固有成本相关的东西。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31698296

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档