【发布时间】:2015-07-29 10:46:59
【问题描述】:
我一直在尝试做一个实验,看看函数中的局部变量是否存储在堆栈中。
所以我写了一点性能测试
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位)
/编辑
在 Firefox 39 上,无论顺序如何,每次测试都需要大约 5500 毫秒。它似乎只发生在特定引擎上。
/Edit2
将函数内联到测试函数使其始终在同一时间运行。
如果函数参数始终是相同的函数,是否有可能进行内联函数参数的优化?
【问题讨论】:
-
我猜这与垃圾收集有关。垃圾收集将在收集器出现并清理所有剩余物之前创建已用内存的峰值。如果你改变功能的顺序会有什么不同吗?
-
尝试切换测试:首先针对
inversed运行,然后针对straight。 -
在 V8 和 Spidermonkey 中得到确认。即使
inversed和straight具有完全相同的定义,也会发生这种情况。可能调用多个函数会产生额外的开销。 -
@KrzysztofWende 这也是我一直在阅读的内容。我没有发现任何迹象表明堆栈内存会被 bc 清除,我也看不出这会很有用的直接原因。我也不是这方面的专家,但这个问题的答案对于任何程序员来说都可能很有趣。最终可能值得赏金。
-
也许
fn是内联的,直到它可以采用多个值。
标签: javascript performance v8